다음 코드가 포함된 bash 스크립트를 보고 있습니다.
#!/bin/sh
set -e # Exit if any command fails
# If multiple args given run this script once for each arg
test $2 && {
for arg in $@
do $0 $arg
done
exit
}
.
.
.
주석에서 언급했듯이 목적은 "인수가 여러 개인 경우 각 인수에 대해 스크립트를 실행합니다"입니다. 이를 테스트하기 위한 실행기 코드가 있습니다.
# install-unit
# If multiple args given run this script once for each arg
test $2 && {
echo "\$0: $0"
echo "\$1: $1"
echo "\$2: $2"
echo "test \$2 && is true"
}
test $2 && {
# note this is just a regular bash for loop
# http://goo.gl/ZHpBvT
for arg in $@
do $0 $arg
done
exit
}
echo "running: $1"
다음과 같은 결과를 제공합니다.
sh ❯ ./multiple-run.sh cats and dogs and stuff
$0: ./multiple-run.sh
$1: cats
$2: and
test $2 && is true
running: cats
running: and
running: dogs
running: and
running: stuff
sh ❯ ./multiple-run.sh cats
running: cats
test $2 && {}
누군가가 그 부분과 exit
내장 쉘을 풀 수 있기를 바랍니다 . 처음에는 test $2
인수가 더 있는지 확인하는 줄 알았는데 , 그럴 수도 있겠네요. 그런데 "and"로 구분된 표현식이 두 개 있는 것 같아서 이상하게 보이고, 내장 함수가 정확히 무슨 일을 하는 &&
지도 헷갈립니다. exit
.
예제와 문서 참조가 포함된 간단한 영어 설명을 부탁드립니다 :)
감사해요!
편집자: Stéphane Chazelas에게 감사드립니다. for 루프 구문의 변경 사항으로 인해 혼란스러워하는 사람은 이 문서의 3번 항목을 확인하세요.괴짜 물건기사. 결론적으로:
echo "positional parameters"
for arg do
echo "$arg"
done
echo "\nin keyword"
for arg in "$@"
do echo "$arg"
done
우리에게 줘:
❯ ./for-loop-positional.sh cats and dogs
positional parameters
cats
and
dogs
in keyword
cats
and
dogs
답변1
이것은 잘못된 작성 방법입니다.
#!/bin/sh -
set -e # Exit if any command fails
# If multiple args given run this script once for each arg
if [ "$#" -gt 1 ]; then
for arg do
"$0" "$arg"
done
exit
fi
작성자가 원하는 것은 두 번째 매개변수가 비어 있지 않은 문자열인지 확인하는 것이라고 생각합니다. 이는 두 번째 매개변수가 전달될 수 있지만 빈 문자열이기 때문에 매개변수가 2개 이상 있는지 확인하는 것과 다릅니다.
test somestring
짧은 형식
test -n somestring
somestring
빈 문자열이 아닌 경우 true를 반환합니다. ( test ''
false를 반환하고 test anythingelse
true를 반환합니다(그러나 test -t
일부 쉘에서는 stdout이 터미널인지 확인하기 위해 검사됩니다)).
그러나 작성자는 변수 주변의 따옴표(실제로는 모든 변수)를 잊어버렸습니다. 이것이 의미하는 바는 $2
분할+글로브 연산자에 따라 다릅니다. 따라서 $2
문자 $IFS
(기본적으로 공백, 탭, 줄 바꿈) 또는 전역 문자( *
, ?
, )가 포함되어 있으면 [...]
제대로 작동하지 않습니다 .
비어 있는 경우 $2
(예: 2개 미만의 인수가 전달되거나 두 번째 인수가 비어 있는 경우) 대신 , test $2
가 됩니다 . 인수를 전혀 받지 않습니다(비어 있거나 그렇지 않은 경우).test
test ''
test
다행히 test
이 경우 어떤 매개변수도 false를 반환하지 않습니다. true를 반환하는 것보다 약간 낫기 test -n $2
때문에(이것은 test -n
와 동일 해지기 때문에 test -n -n
) 일부 경우에는 이 코드가 작동하는 것 같습니다.
요약하다:
2개 이상의 매개변수가 전달되는지 테스트합니다.
[ "$#" -gt 1 ]
또는
[ "$#" -ge 2 ]
변수가 비어 있지 않은지 테스트합니다.
[ -n "$var" ] [ "$var" != '' ] [ "$var" ]
이들 모두는 POSIX 구현에서 신뢰할 수 있지만
[
아주 오래된 시스템을 처리해야 한다면 다음을 사용해야 할 수도 있습니다.[ '' != "$var" ]
반면 , , ...와
[
같은 값을 구현하는 경우 에는$var
=
-t
(
변수가 정의되었는지 테스트합니다(스크립트에 두 번째 인수가 전달되었는지 테스트하는 데 사용할 수 있지만
$#
읽기 쉽고 사용하기 더 관용적입니다).[ "${var+defined}" = defined ]
(또는 그에 상응하는 . 명령 에 별칭을 test
사용하는 것이 더 일반적입니다 .)[
test
cmd1 && cmd2
이제 와 의 차이점에 대해 이야기해 보세요 if cmd1; then cmd2; fi
.
cmd2
둘 다 cmd1
성공할 때만 실행됩니다. 이 경우의 차이점은 전체 명령 목록의 종료 상태가 &&
이 경우 실행된 마지막 명령의 종료 상태가 된다는 것입니다.실패하다코드는 cmd1
true를 반환하지 않지만(여기서는 아무 문제도 발생하지 않지만 set -e
)), 이 경우 실행되지 않으면 0(성공)이 if
됩니다 .cmd2
cmd2
그래서 다음 cmd1
과 같이 사용됩니다.상황(실패로 간주되지 않는 경우질문), 일반적으로 이를 사용하는 것이 가장 좋습니다. if
특히 스크립트의 종료 상태를 정의하므로 스크립트에서 마지막으로 수행하는 작업인 경우 더욱 그렇습니다. 또한 코드가 더 명확해집니다.
이 cmd1 && cmd2
형식은 다음과 같이 더 일반적으로 사용됩니다.상황그들은 스스로 다음을 좋아합니다:
if cmd1 && cmd2; then...
while cmd1 && cmd2; do...
이는 이 두 명령의 종료 상태에 관심이 있는 경우입니다.
답변2
test $2 && some_command
이는 두 가지 명령으로 구성됩니다.
test $2
$2
두 번째 인수( )의 확장된 문자열의 길이가 0이 아닌지 확인합니다 . 즉,test -n $2
([ -n $2 ]
)을 확인해야 합니다. 공백이 있는 값 은 주위에 따옴표를 사용하지 않으므로 차단됩니다$2
. 이것을test
사용해야합니다test "$2"
.&&
단락 평가 연산자입니다. 즉,&&
이전 명령이 성공한 경우에만 다음 명령이 실행됩니다(즉, 종료 코드가 0임). 따라서 위의 예에서는 성공하는some_command
경우에만 실행됩니다 (즉, 문자열이test $2
길이가 아닌 경우). 그런 다음some_command
실행됩니다.