【问题标题】:Conditional Statement Command Syntax Error in Bash ScriptBash 脚本中的条件语句命令语法错误
【发布时间】:2023-01-13 00:29:02
【问题描述】:

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

#! /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 &lt;(echo $md5hash) &lt;(echo $filehash),这没有任何问题。我也试图逃避括号,但也失败了。我很困惑为什么这会导致问题。

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

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

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

总之,我的问题是:

  1. 为什么脚本在尝试解释原始条件语句中的 $( diff &lt;(echo $md5hash) &lt;(echo $filehash) 时会因语法错误而失败?

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

    提前致谢!

【问题讨论】:

  • $(diff ...) 周围加上双引号
  • if cmp -s &lt;(md5sum install_package.tgz) &lt;(cat install_package.tgz.md5); then foo; else bar; fi也许吧。
  • 整个脚本可以简化为if md5sum -c install_package.tgz.md5 &gt;/dev/null 2&gt;&amp;1; then echo "File Integrity Check Passed"; else echo "File Integrity Check Failed"; exit; fi

标签: bash conditional-statements syntax-error unexpected-token


【解决方案1】:
  1. diff 产生了不止一个字的输出。当它被替换为 if 命令时,你会得到类似的东西
    if [ -z '1c1' '<' 'abc' '---' '>' 'def' ]
    

    这不是有效的 test 表达式。您需要引用它,以便所有输出都被视为一个单词。

    if [ -z "$( diff <(echo $md5hash) <(echo $filehash) )" ]
    
    1. 我能想到的唯一原因是
    if [ "$filehash" = "$md5hash" ]
    

    是两个字符串中存在空格差异。也许 install_package.tgz.md5 以 CRLF 结尾,所以 CR 被留在 $md5hash 中。但是我不确定为什么当您从[ 更改为[[ 时它可以正常工作,他们都应该对此很敏感。

【讨论】:

    【解决方案2】:

    当您针对 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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-30
      相关资源
      最近更新 更多