我正在尝试编写一个具有以下逻辑的简单脚本:如果第一个参数是有效的常规文件,则运行 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"
那么它就什么都没有并消失。然后执行的代码是(如 shell-x
选项所报告的):
[ -f ]
其中,-f
长度不为零的字符串会导致真正的测试并运行该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
,它也没有被引用(也是问题的一部分),shell将表达式视为[ -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 '' ']'