shell 脚本有有趣的 bug

shell 脚本有有趣的 bug

我发现了 bash 的这种行为GNU bash, version 4.3.30(1)-release (x86_64-pc-linux-gnu),甚至在 Debian 上发现了最新的(如何获取 dash 版本?) dash 的行为。

错误原样:

/bin/echo "Silent Err 'unexpected EOF while looking for matching' Example:"

if [ 0 -eq 1 ]; then
        /bin/echo "HERE IS MISTAKE WITHOUT QUOTE IN THE END
        exit
fi

/bin/echo " BLACK HOLE "
/bin/echo " CODE WILL NEVER PROCEED "

if [ 0 -eq 1 ]; then
        /bin/echo "SECOND MISTAKE
        exit
fi
/bin/echo "normal code... will work";
/bin/echo "Good and silent exit without any notice about BLACK HOLE code..."
/bin/echo "exit."

发射:

# bash bug_as_is.sh 
Silent Err 'unexpected EOF while looking for matching' Example:
normal code... will work
Good and silent exit without any notice about BLACK HOLE code place...
exit.

仅当第一个if then fi块被引用时,才会出现错误:

# bash unbug.sh 
Silent Err 'unexpected EOF while looking for matching' Example:
 BLACK HOLE 
 CODE WILL NEVER PROCEED 
unbug.sh: line 20: unexpected EOF while looking for matching `"'
unbug.sh: line 24: syntax error: unexpected end of file

这是常见的已知错误还是我发现了真正的钻石? (;

这种行为的支柱是什么?

答案1

bash 中没有错误:代码正常工作。

bash 允许多行字符串作为参数,echo即使这些字符串看起来很奇怪并且包含 bash 代码。

请注意,以下只是一个echo带有多行字符串输出的语句:

        /bin/echo "HERE IS MISTAKE WITHOUT QUOTE IN THE END
        exit
fi

/bin/echo " BLACK HOLE "
/bin/echo " CODE WILL NEVER PROCEED "

if [ 0 -eq 1 ]; then
        /bin/echo "SECOND MISTAKE

为了澄清这一点,让我们用 替换那个长字符串"multiline string omitted"。那么,代码很简单:

/bin/echo "Silent Err 'unexpected EOF while looking for matching' Example:"

if [ 0 -eq 1 ]; then
        /bin/echo "multiline string omitted"
        exit
fi
/bin/echo "normal code... will work";
/bin/echo "Good and silent exit without any notice about BLACK HOLE code..."
/bin/echo "exit."

以上是正常工作的代码。

答案2

我不确定“这种行为的支柱”是什么意思,但据我解释:

(看似)不匹配的带引号的字符串"HERE IS MISTAKE WITHOUT QUOTE IN THE END实际上只是开始带引号的字符串文字。该字符串文字超出了第一个字符fi,并包含了以 开头的双引号字符之前的所有内容"SECOND MISTAKE

因此,bash可以解析整个混乱,尽管从人类的角度来看是不正确的。事实证明,由于 1 在数字上不等于 0,因此从/bin/echo "HERE IS MISTAKEfi后面的整个代码块"SECOND MISTAKE都不会被执行。因此,(明显的)字符串SECOND MISTAKE被正确解析为可能的命令,但bash从未尝试执行它,因此我们没有看到任何错误SECOND: command not found或其他错误。

总而言之,两行缺少引号会导致bash将代码解析为 single 的“true”子句if-then-fi,但条件为 false,因此bash永远不要尝试执行人眼认为是错误的命令,并且不会执行给出相关的语法错误。

相关内容