【问题标题】:Why does commenting out seemingly-unrelated code in this simple shell script throw an error?为什么在这个简单的 shell 脚本中注释掉看似无关的代码会引发错误?
【发布时间】:2020-11-11 03:05:04
【问题描述】:

这让我很难过。刚接触 shell 脚本并在 macOS Catalina 中使用 ZSH(尽管我认为在 bash 中也会发生同样的事情。)

我正在使用以下脚本,并将其保存在一个名为 f 的文件中,该文件没有扩展名。我用-x chmod'd 将它放在我的路径变量中的本地bin 文件夹中。

clear

echo "Argument Count: $#"

if [ $# == 0 ]; # Run if no arguments
then 
    echo "You ran this with no arguments!"
    exit 0
fi

if [ $1 == "a" ]; # Run if the first argument is 'a'
then
    echo "You ran A!"
    exit 0
fi

# Run if nothing matches the above
echo "No matches!"

以上工作如我所料。如果我输入这个...

f

我明白了……

Argument Count: 0
You ran this with no arguments!

如果我输入这个...

f a

我明白了……

Argument Count: 1
You ran A!

最后,如果我输入这个...

f b (or f c, f foo, etc.)

我明白了……

Argument Count: 1
No matches.

再次,完全按照我的预期工作。

但是,如果我将脚本更改为这样,我只需注释掉第一个 if 块...

clear

echo "Argument Count: $#"

# if [ $# == 0 ]; # Run if no arguments
# then 
#   echo "You ran this with no arguments!"
#   exit 0
# fi

if [ $1 == "a" ]; # Run if the first argument is 'a'
then
    echo "You ran A!"
    exit 0
fi

# Run if nothing matches the above
echo "No matches!"

...我自己输入f,我现在明白了!

Argument Count: 0
/Users/[redacted]/bin/f: line 11: [: ==: unary operator expected
No matches!

注意:第 11 行是带有注释的行 # Run if the first argument is 'a'

更奇怪的是,如果我输入以下内容,它会直接运行它所抱怨的第 11 行的代码...

f a

我明白了,它工作正常!

Argument Count: 1
You ran A!

那么我到底错过了什么??

【问题讨论】:

    标签: bash shell zsh macos-catalina


    【解决方案1】:

    当您运行不带参数的脚本时,此表达式:

    if [ $1 == "a" ]; 
    

    变成:

    if [ == "a" ];
    

    这在语法上无效。您注释掉的代码通常可以保护您免受这种情况的影响,因为如果没有参数,它会导致脚本退出。

    这就是为什么你应该总是引用变量,例如:

    if [ "$1" == "a" ]; 
    

    即使$1 未定义,它也会正确评估。

    如果您正在为 bash 编写脚本,则可以利用 [[ ... ]] 表达式,它与 [ ... ] 非常相似,但不需要同样注意引号。如果你要写:

    if [[ $1 == "a" ]];
    

    它会按需要工作。 zsh 可能有类似的东西,但我不确定。

    【讨论】:

    • 这就是我喜欢 StackOverflow 的原因! :) 当你看到它时,它是如此简单。顺便说一句,只是出于好奇,如果我想让 if 语句检查不区分大小写,你能举个例子吗?还有一件事……我一直看到人们使用-eq 而不是==。有区别吗?
    • 对于不区分大小写的检查,我可能只写if [ "$1" = a ] || [ "$1" = A ];但请参阅this question 了解各种替代方案。 -eq 是一个数字比较器,而=(又名==)是一个字符串比较器(所以00 -eq 0 为真,但00 = 0 为假)。
    • 由于== 运算符实际上是[[...]] 中的模式匹配 运算符,因此您可以使用if [[ $1 == [aA] ]]
    • 更好!谢谢!我只需要测试它是否在 ZSH 下工作,因为它现在是默认 shell。实际上,关于这一点,如果您在文件顶部有注释 #!/bin/bash,这是否意味着“即使您从 zsh 运行此脚本,当此脚本运行时,它也会在 bash 下运行”?
    • 如果您的脚本是可执行的 (chmod +x myscript.sh),那么是的,“she-bang”行决定了使用哪个解释器来运行脚本。除非您明确指定解释器(zsh myscript.shbash myscript.shpython myscript.sh 等)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-25
    • 2019-05-13
    相关资源
    最近更新 更多