POSIX

POSIX

sed다음과 같이 (null이 아닌 것으로 알려진 ) 외부 유틸리티를 호출하여 $myvar이 작업을 수행 할 수 있습니다.

if [ "$(printf %s "$myvar" | sed -n '$=')" -eq 1 ]; then
  echo "Your variable has only one line, proceeding"
else
  echo "Error condition, variable must have only one line"
fi

bash내장된 함수만 사용하여 이를 수행할 수 있는 방법이 있습니까 ?

더 좋은 점은 외부 유틸리티를 호출하지 않고 POSIX 지정 방식으로 이 작업을 수행할 수 있는 방법이 있습니까?


(이 질문은 호기심과 더 나은 작업 방법을 찾는 것 중 하나입니다. 위의 코드는하다기능. 더 깨끗하고 빠른 방법이 있는지 궁금합니다. )

답변1

POSIX 방식:

NL='
'
case $myvar in
  *"$NL"*) echo more than one line ;;
        *) echo one line ;;
esac

이는 POSIX 이전 Bourne 유사 쉘에도 적용됩니다.

답변2

여러 가지 옵션이 있습니다(bash 우선, 아래 POSIX).
각 함수 내부의 코드는 외부에서도 쉽게 사용할 수 있습니다.

#!/bin/bash

nl=$'\n'

aregex   (){ [[ $a =~        $nl     ]]; }
apattern (){ [[ $a ==       *$nl*    ]]; }
acut     (){ [[ $a != "${a%%"$nl"*}" ]]; }
areplace (){ [[ $a != "${a//"$nl"/}" ]]; }
acase    (){ case $a in (*$nl*) true;; (*) false;; esac; }
aifs     ()( IFS="$nl"
             set -f; set -- x${a}x;
             (( $# > 1 ));
           )
aread    (){ IFS="$nl" read -rd '' -a b <<<"x${a}x";
             (( "${#b[@]}" > 1 )); }

모든 기능은 옵션입니다. 줄이 하나만 있는 경우 각 함수는 0 값으로 종료되고, 변수 $a에 개행 문자가 여러 개 있는 경우(multiple ) $'\n'1 의 값으로 종료됩니다.

함수를 실행하면 필요한 줄이 인쇄됩니다.

out=''; "$function" && out="more than "
printf "%9s   = %sone line\n" "$1" "$out"

모든 옵션을 실행합니다:

a='ab'"$nl"'cd' ; alltests
a='ab  cd'      ; alltests

다음과 같은 출력을 제공합니다.

   aregex   = more than one line
 apattern   = more than one line
     acut   = more than one line
 areplace   = more than one line
    acase   = more than one line
     aifs   = more than one line
    aread   = more than one line

   aregex   = one line
 apattern   = one line
     acut   = one line
 areplace   = one line
    acase   = one line
     aifs   = one line
    aread   = one line  

POSIX

다음 옵션은 여러 가지 이유로 POSIX에서 실패합니다.

  • =~areregex: POSIX에는 정규식 연산자가 없습니다.
  • ==apattern: POSIX에는 연산자가 없습니다.
  • areplace: 매개변수 확장에는 옵션이 없습니다 ${ / / }.

그 중 4개는 POSIX로 안전하게 변환될 수 있습니다.

  • posixcut: 아마도 가장 좋은 솔루션일 것입니다.
  • posixcase : POSIX 쉘을 위한 일반적인 솔루션입니다.
  • posixifs: setup을 활성화하기 위해 서브셸 내에서 실행됩니다 set -f.
  • -dposixread: 읽기에는 또는 가 없지만 -a수정될 수 있습니다.

#!/bin/dash

nl='
'

posixcut (){ [ "${a}" != "${a%%"$nl"*}" ] ; }
posixcase(){ case $a in (*$nl*) true;; (*) false;; esac; }
posixifs ()( IFS="$nl";
             set -f; set -- x${a}x;
             [ "$#" -gt 1 ];
           )
posixread(){ local b=0;
             while IFS=$nl read -r _; do
                 b=$((b+1));
                 [ $b -gt 1 ] && break;
             done <<-_EOT_
x${a}x
_EOT_
             [ $b -gt 1 ];
           }

노트: 예, local기술적으로 POSIX는 아니지만좋은 지원을 받다.
Local 은 b안전하게 제거할 수 있습니다(전역 $b사용량 확인).

본 슈프리머시(1977 Shell).

1977년의 원래 Bourne 셸에 대한 코드가 필요한 경우 다음 코드를 사용하세요.

posixcase() { case $a in *$nl*) true;; *) false;; esac; }
posixifs () ( IFS="$nl"
              set -f; set -- x${a}x;
              [ "$#" -gt 1 ];
            )
bourneread()( b=0                ### A helper function.
              while :; do
                  if IFS=$nl read c && [ $b -le 1 ]; then
                      b=`expr $b + 1`
                  else
                      echo "$b"
                      break
                  fi    
              done <<-_EOT_
x${a}x
_EOT_
             )
posixread   (){ [ `bourneread` -gt 1 ]; }

posixcut에서 사용되는 확장은 ${a%% }Bourne에서 작동하지 않습니다. Bourne에서 작동하려면 posixif를 두 부분으로 나누어야 합니다.
읽기 옵션에는 상당한 변경이 필요하지만 정상적으로 작동합니다.
해당 기능은 posixread이고 bourneread는 필수 보조 기능입니다.

Bourne의 모든 코드는 작동 테스트를 거쳤습니다.가보 껍질.

답변3

다음 코드 조각은 작동합니다 bash(옵션 유무에 관계 없음 -posix).

#!/bin/bash
#!/bin/bash -posix
version_1 () { [[ "$myvar" = *$'\n'* ]]; }
version_2 () {
  local newlines="${myvar//[^$'\n']/}"
  [[ "${#newlines}" -eq 1 ]]
}
for test in version_1 version_2; do
  if $test; then echo many lines; else echo one line; fi
done

답변4

다음과 같이 Bash 매개변수 확장을 사용하는 것이 좋습니다.

n="${myvar//[^\n]}"; if [ ${#n} -eq 1 ]; then
  echo "Your variable has only one line, proceeding"
else
  echo "Error condition, variable must have only one line"
fi

테스트 샘플:

myvar="xxx"
myvar="xx\nxx"
myvar="xx\nx\nx"

관련 정보