我发现了 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 MISTAKE
到fi
后面的整个代码块"SECOND MISTAKE
都不会被执行。因此,(明显的)字符串SECOND MISTAKE
被正确解析为可能的命令,但bash
从未尝试执行它,因此我们没有看到任何错误SECOND: command not found
或其他错误。
总而言之,两行缺少引号会导致bash
将代码解析为 single 的“true”子句if-then-fi
,但条件为 false,因此bash
永远不要尝试执行人眼认为是错误的命令,并且不会执行给出相关的语法错误。