이것은 OSX에서 완벽하게 작동합니다
#!/bin/bash
chars=( {a..z} )
n=3
for ((i=0; i<n; i++))
do
echo "${chars[i]}"
done
그러나 우분투에서 실행할 때 다음 오류가 발생합니다.
ForLoopAlphabetTest.sh: 2: ForLoopAlphabetTest.sh: Syntax error: "(" unexpected
문제를 해결할 수없는 것 같습니다. 어떤 제안?
이것은 OSX에서 완벽하게 작동합니다
#!/bin/bash
chars=( {a..z} )
n=3
for ((i=0; i<n; i++))
do
echo "${chars[i]}"
done
그러나 우분투에서 실행할 때 다음 오류가 발생합니다.
ForLoopAlphabetTest.sh: 2: ForLoopAlphabetTest.sh: Syntax error: "(" unexpected
문제를 해결할 수없는 것 같습니다. 어떤 제안?
답변:
아마도 다음과 같이 스크립트를 실행하고있을 것입니다.
sh ForLoopAlphabetTest.sh
우분투으로 sh
하는 심볼릭 링크된다 dash
; 같은 dash
배열의 개념이 없습니다, 당신은 구문 오류를 얻고있다 (
.
이 스크립트는에서 완벽하게 작동 bash
하므로 bash
인수 로 실행하면 괜찮습니다 .
bash ForLoopAlphabetTest.sh
이제 bash
스크립트에 shebang이 있으므로 스크립트를 실행 파일 ( chmod u+x ForLoopAlphabetTest.sh
)로 만들고 다음과 같이 실행할 수 있습니다.
/path/to/ForLoopAlphabetTest.sh
또는 스크립트 디렉토리에서 :
./ForLoopAlphabetTest.sh
또한 스크립트에는 중괄호 확장 {a..z}
과 C 스타일 for
구문이 for (( ... ))
포함되어 있습니다 dash
. 따라서 목표가 이식성이라면 POSIX sh
구문 만 살펴 봐야 합니다.
/bin/sh
유닉스 계열 운영 체제에서 실행할 수있는 이식 가능한 스크립트를 작성 하려면 배열을 사용할 수 없습니다. Bash (및 다른 쉘)는 매우 편리하고 항상 더 이식 가능한 코드로 쉽게 대체 할 수 없기 때문에 추가했습니다. 그러나 스크립트의 경우 특히 bash 특정 기능을 사용하지 않고도 문제없이 수행 할 수 있습니다. 그렇게하는 방법에 관심이 있습니까?
sh
스크립트는 모든 Bourne 스타일 쉘에서 제공하지 않는 Bash 쉘의 세 가지 기능을 사용합니다. 으로 heemayl는 말한다 , 당신은 단순히 함께 해당 스크립트를 실행할 수 있습니다 bash
대신 sh
. 귀하의 hashbang의 상단 (시 라인 #!/bin/bash
)을 지정 bash
당신이 경우 만 효과가 실행 으로 스크립트를 heemayl 설명 . 당신이 스크립트의 이름을 전달하면 sh
, sh
자동으로 호출하지 않습니다 bash
, 단순히 스크립트를 실행합니다. 때문입니다 스크립트가 실제로 실행되면, hashbang 라인은 효과가 없습니다 .
다른 대안 은 Bash 기능에 의존하지 않는 완전히 이식 가능한 스크립트 를 작성 해야하는 경우 스크립트없이 변경되도록 스크립트를 변경하는 것입니다. 사용하는 Bash 기능은 다음과 같습니다.
( {a..z} )
할당 된 괄호로 묶은 expression chars
은 배열을 만들고 ${chars[i]}
루프에 표시 되는 배열을 만듭니다 .{a..z}
로 확장되었습니다 a b c d e f g h i j k l m n o p q r s t u v w x y z
. 그러나 이것은 Bourne 스타일 쉘의 보편적 인 (또는 표준화 된) 기능이 아니며 Dash는이를 지원하지 않습니다.for
-loop 구문 . 비록 Bash에만 국한되지 는 않는 산술 확장 에 기초 하지만 (일부는 POSIX 호환이 아닌 오래된 쉘 도 없지만) C 스타일 루프 는 Bash-ism이며 널리 이식되지 않습니다. 다른 껍질.for
Bash는 특히 Ubuntu와 같은 GNU / Linux 시스템에서 광범위하게 사용할 수 있으며 macOS 및 기타 여러 시스템에서도 사용할 수 있습니다. Bash 전용 기능을 얼마나 많이 사용하고 있는지를 고려할 때 스크립트를 실행할 때 Bash (또는 사용중인 기능을 지원하는 다른 쉘)를 사용하고 싶을 수도 있습니다.
그러나 원하는 경우 이식 가능한 구성으로 바꿀 수 있습니다. 배열과 C 스타일 for
루프는 쉽게 교체 할 수 있습니다. 중괄호 확장없이 (및 스크립트에서 하드 코딩하지 않고) 문자 범위를 생성하는 것은 약간 까다로운 부분입니다.
먼저 소문자 라틴 문자를 모두 인쇄하는 스크립트가 있습니다.
#!/bin/sh
for i in $(seq 97 122); do
printf "\\$(printf %o $i)\n"
done
seq
명령은 숫자 시퀀스를 생성합니다. 명령 대체를$(
)
수행 하므로 의 출력으로 대체됩니다 . 이것들은 through 의 문자 코드 입니다 .$(seq 97 122)
seq 97 122
a
z
printf
명령 문자 (예를 들어, 문자 코드로 바꿀 수 printf '\141'
인쇄 a
a로 이어 개행 )하지만, 코드가 있어야 8 진수 동안 seq
만 출력 진수 . 따라서 printf
두 번 사용 했습니다. inner printf %o $i
는 십진수 (로 제공 seq
)를 8 진수 로 변환하고 외부 명령 으로 대체 합니다 printf
. ( 16 진수 를 사용할 수도 있지만 더 간단하지 않고 이식성이 떨어 집니다.)printf
\
그 뒤에 8 진수가 해당 코드의 문자 및 \n
개행 문자로 해석 됩니다 . 그러나 쉘 은 또한 \
이스케이프 문자로 사용 합니다. \
앞에 $
방지 할 수 $
에서 발생하는 확장의 원인 (이 경우, 명령 치환 )을하지만 난 그것을 방지하기 위해 싶지 않아, 내가 서로를 탈출 있도록 \
; 그것이 이유입니다 \\
. 은 초 \
전에 n
달리하기 때문에 탈출 할 필요가 없습니다 \$
, \n
이중 인용 문자열에 쉘에 특별한 의미를 가지고 있지 않습니다.'
)도 쉘 인용 구문의 중요한 부분입니다.이 스크립트에서는 따옴표를 사용하지 않았습니다.이것은 대부분의 유닉스 계열 시스템에 이식 가능하며 사용하는 Bourne 스타일 쉘에 의존하지 않습니다. 그러나 유닉스 계열 시스템은 seq
기본적으로 설치되어 있지 않습니다 ( jot
대부분의 GNU / Linux 시스템에서는 기본적으로 설치되지 않는 대신 사용 하는 경향이 있습니다 ). 다음과 같은 경우 루프를 사용 expr
하거나 산술 대체를 사용하여 이식성을 더욱 높일 수 있습니다.
#!/bin/sh
i=97
while [ $i -le 122 ]; do
printf "\\$(printf %o $i)\n"
i=$((i + 1))
done
즉, 사용 while
과 -loop을 명령 경우에만 루프 계속 범위이다.[
$i
스크립트는 전체 알파벳을 인쇄하는 대신 변수를 정의 n
하고 첫 번째 $n
소문자를 인쇄합니다 . Bash 전용 기능에 의존하지 않고 Dash에서 작동하지만 다음과 같은 스크립트 버전이 있습니다 seq
.
#!/bin/sh
n=3 start=97
for i in $(seq $start $((start + n - 1))); do
printf "\\$(printf %o $i)\n"
done
n
스크립트에서와 같이 인쇄되는 문자 수 를 변경 하여 값을 조정합니다 .
필요하지 않은 버전은 다음과 같습니다 seq
.
#!/bin/sh
n=3 i=97 stop=$((i + n))
while [ $i -lt $stop ]; do
printf "\\$(printf %o $i)\n"
i=$((i + 1))
done
, 거기에 $stop
하나 더 제가 사용하므로, 즉 인쇄되어야한다 마지막 문자의 문자 코드보다 -lt
가 아닌 (보다 작음) -le
(이하)을 가진 [
명령. (또한 만들고 stop=$((i + n - 1))
사용 하기 위해 노력했을 것입니다 [ $i -le $stop ]
).