다음 논리를 사용하여 간단한 스크립트를 작성하려고 합니다. 첫 번째 인수가 유효한 일반 파일이면 for 루프를 실행하고, 인수가 제공되지 않으면 "code2"를 실행하고, 그렇지 않으면 "code3"을 실행합니다. 아래 스크립트는 제게는 잘 작동하는 것 같지만 인수 없이 실행하면 중단됩니다.
#!/bin/bash
if [ -f $1 ]; then
for i in `cat $1`
do
<something>
done
elif [ $# -eq 0 ]; then
"code2"
else
"code3"
fi
이것은 디버그 출력이며, 마지막에 멈췄습니다.
bash -x myscript
+ '[' -f ']'
++ cat
매개변수를 제공하지 않았는데 왜 여전히 첫 번째 if-then 흐름에 도달합니까? 저는 bash 스크립팅을 처음 접했습니다. 어떤 도움이라도 대단히 감사하겠습니다.
답변1
변수를 참조하지 않으면 "$1"
아무것도 없고 사라집니다. 그런 다음 실행되는 코드는 다음과 같습니다( -x
셸 옵션에 보고됨).
[ -f ]
여기서 -f
길이가 0이 아닌 문자열로 인해 실제 테스트가 해당 섹션을 실행하게 됩니다 then
.
(적어도) 다음과 같이 작성해야 합니다.
[ -f "$1" ]
빈 인수가 있으면 다음과 같습니다.
[ -f "" ]
파일 일치 실패를 보고합니다 ""
.
또 다른 대안은 매개변수 확장을 사용하는 것입니다(외부 참조가 필요하지 않음).
[ -f ${1:-""} ]
""
값이 $1
null이거나 비어 있으면 로 확장됩니다.
그리고 파일 줄을 반복하기 위해 for 루프를 수행하지 마십시오. while read
루프 사용을 고려해야 합니다
#!/bin/sh
if [ -f ${1:-""} ]; then
while read -r line; do
echo '<something>'
done <"$1"
elif [ "$#" -eq 0 ]; then
echo "code2"
else
echo "code3"
fi
답변2
간단한 대답은 존재하지 않는 것에 대해서도 $1
인용되지 않았기 때문입니다(또한 문제의 일부). 쉘은 표현식을 다음과 같이 취급하며 [ -f ]
여기에 표시되는 -f
것은 [
플래그로 인식되지 않고 단지 단일 "표현식 ". 실제로는 다음과 같습니다.
$ [ abracadabra ] && echo "success"
success
그리고 매뉴얼을 인용합니다 test
(모르는 경우 별칭임 [
).
An omitted EXPRESSION defaults to false. Otherwise, EXPRESSION is true or false and sets exit
status. It is one of:
( EXPRESSION )
EXPRESSION is true
표현식을 인용하면 출력을 추적할 때 다음과 같이 보일 것입니다. 즉, 실제로 빈 문자열을 기존 파일 이름으로 평가하려고 시도합니다.
$ (set -x; [ -f "$this_var_doesnt_exist" ] && echo "hi" )
+ '[' -f '' ']'