Bash 脚本中的条件语句命令语法错误

Conditional Statement Command Syntax Error in Bash Script

提问人:g9s0x1 提问时间:1/12/2023 最后编辑:g9s0x1 更新时间:1/13/2023 访问量:59

问:

我在其他人编写的脚本中遇到了条件语句的命令语法问题。脚本如下(截断)。

#! /bin/bash

# app_upgrade.sh

# Verify file integrity
filehash=$( md5sum install_package.tgz )
md5hash=$( cat install_package.tgz.md5 )

if [ -z $( diff <(echo $md5hash) <(echo $filehash) ) ]; then
    printf "File Integrity Check Passed"
else
    printf "File Integrity Check Failed"
    exit
fi

当我运行此脚本时,由于意外的左括号,它在尝试解释条件语句时失败。报告给 CLI 的确切错误如下所示。

app_upgrade.sh: command substitution: line 118: syntax error near unexpected token `('
app_upgrade.sh: command substitution: line 118: ` diff <(echo $md5hash) <(echo $filehash) )'

我验证了 diff 是与运行脚本的用户相同的用户在我的系统上的可执行命令。我还从 CLI 运行了它,这没有任何问题。我也试图转义括号,但这也失败了。我很困惑为什么这会导致问题。diff <(echo $md5hash) <(echo $filehash)

作为一种解决方法,我尝试了其他一些条件,因为如果我一开始就编写脚本,我就不会使用 diff 进行比较。我尝试了以下替换上述脚本中指定的条件。

if [ "$filehash" = "$md5hash" ]但是,这没有奏效。即使哈希值相同,条件也会导致比较意外失败。

if [[ "$filehash" == "$md5hash" ]]这终于奏效了。

总而言之,我的问题是:

  1. 为什么脚本在尝试解释原始条件语句时失败并出现语法错误?$( diff <(echo $md5hash) <(echo $filehash)

  2. 在我更新的条件语句中,假设两个哈希值相同,为什么失败但成功?根据我的研究,看起来两者都是在 bash 中比较字符串的有效方法。if [ "$filehash" = "$md5hash" ]if [[ "$filehash" == "$md5hash" ]]

提前致谢!

bash 条件语句 语法错误 意外令牌

评论

0赞 Barmar 1/12/2023
把双曲子放在周围$(diff ...)
0赞 Jetchisel 1/13/2023
if cmp -s <(md5sum install_package.tgz) <(cat install_package.tgz.md5); then foo; else bar; fi或。
2赞 M. Nejat Aydin 1/13/2023
整个脚本可以简化为if md5sum -c install_package.tgz.md5 >/dev/null 2>&1; then echo "File Integrity Check Passed"; else echo "File Integrity Check Failed"; exit; fi
0赞 chepner 1/13/2023
您似乎实际上并没有用于执行脚本,并且无法识别进程替换。如果使用 类似 的东西,则会忽略 shebang。bashsh app_upgrade.sh ...
0赞 g9s0x1 1/13/2023
@chepner感谢您的评论。这为我指明了正确的方向,因为我确实认为这里与外壳有关的东西导致了我的问题。其他用户可以在同一系统上毫无问题地执行此脚本,但我会因语法错误而失败。请参阅我针对上述原始问题发布的更新。

答:

0赞 Marcin Kłopotek 1/13/2023 #1

当您针对 shellcheck linter 运行脚本时,您可以看到错误

In ./test.sh line 9:
if [ -z $( diff <(echo $md5hash) <(echo $filehash) ) ]; then
        ^-- SC2046 (warning): Quote this to prevent word splitting.
                       ^------^ SC2086 (info): Double quote to prevent globbing and word splitting.
                                        ^-------^ SC2086 (info): Double quote to prevent globbing and word splitting.

您必须引用表达式以避免单词拆分:if

#! /bin/bash

# app_upgrade.sh

# Verify file integrity
filehash=$( md5sum install_package.tgz )
md5hash=$( cat install_package.tgz.md5 )

# mind the `"` quotation marks around 
if [ -z "$( diff <(echo $md5hash) <(echo $filehash) )" ]; then
    printf "File Integrity Check Passed"
else
    printf "File Integrity Check Failed"
    exit
fi

评论

0赞 chepner 1/13/2023
这是关于潜在语义错误(或由 引发的语法错误)的警告,而不是 shell 语法错误。[
0赞 F. Hauri - Give Up GitHub 1/13/2023
警告无用:考虑:!(或我的 ansertcatmd5hash=$(<install_package.tgz.md5);-)
0赞 g9s0x1 1/13/2023
@Marcin Kłopotek 感谢您的 shellcheck linter 建议。我不知道这一点,但这是一个有用的工具。
0赞 g9s0x1 1/13/2023 #2

我的问题与外壳有关。我问题的根本原因是/home/目录中的安全限制,因此我无法从那里运行。但是,工作正常并执行了脚本,但我没有像我预期的那样运行它。使用允许脚本正常运行。因此,这里的根本原因是我执行脚本的目录中的权限问题,导致我错误地使用命令执行 bash 脚本。noexec./app_upgrade.shsh app_upgrade.shbash app_upgrade.shsh

综上所述:

[user@host ~]$ ./app_upgrade.sh结果bash: ./app_upgrade.sh: Permission denied

[user@host ~]$ sh app_upgrade.sh执行了脚本,但不是作为 bash,因此这导致了正确解释其中一行代码的问题。

[user@host ~]$ bash app_upgrade.sh正确执行脚本,没有错误。

如果我最初在没有约束的目录中运行它,那么问题将永远不会出现。noexec

感谢您的所有意见、建议和帮助!