我最近对bash脚本做了一些更改,并在函数中出现语法错误。我知道错误是什么(作业周围的空格:local max_loops = 4
而不是local max_loops=4
)。
然而,我一开始并没有发现它 - 它是一个带有大量输出的长脚本,只是输出错误但是继续运行 - 函数返回true,所以尽管测试了函数是否成功我没有错误。
简化版本在这里:
#!/bin/bash
do_magic(){
local i=1
local max_loops = 4 #### <- WANT TO ABORT ON THIS BUG
while [ $i -le $max_loops ]; do
echo "Loop: $i"
i=$(( i + 1 ))
done
}
if do_magic; then
echo "Ran OK"
else
echo "Error running...."
fi
(我的实际函数在循环中执行操作并在内容失败时返回错误代码)。这只是输出:
$ ./foo.sh
./foo.sh: line 6: local: `=': not a valid identifier
./foo.sh: line 6: local: `4': not a valid identifier
./foo.sh: line 7: [: 1: unary operator expected
Ran OK
我的问题:是否有任何通用方法可以说未处理错误的函数返回非零值?
我已在此修复了实际错误,但我希望让脚本更强大。
答案 0 :(得分:1)
基本上语法无法处理语法错误,因为必须在代码运行之前解析语法。我认为这就是你的假设。
但是,在这种情况下,它不是bash中的语法错误,它是内置[
(或test
)命令引发的语法错误。
请注意[
是外部*命令,它或多或少是test
命令的别名。你可以替换:
[ 1 -lt 2 ]
由:
test 1 -lt 2
例如。
这种错误只能在bash脚本的运行时检测到,并且bash脚本默认不会失败它就像任何其他失败的命令一样。好吧,有一个例外:如果使用set -e
,[
命令不会使脚本失败。
*现在实现了bash内置。但它不是bash 语法
如何解决?
bash
为此提供[[
(扩展比较)(以及其他优势):
foo() {
# Oops! missing the dash in front of 'lt'
if [[ 1 lt 2 ]] ; then
echo "foo"
fi
}
echo "Don't print this"
foo
echo "And this"
由于[[
是bash
语法,而不是外部命令,bash可以在代码运行之前的解析阶段处理此错误。结果是脚本根本不运行。
答案 1 :(得分:0)
这不是syntax error
,而是最常见的Bash pitfalls
local
关键字是内置的Bash。请注意local
,因为出于历史原因,该语句返回一个success status
,您可能不期望(重击manual)。这是一个示例:
local x=$(false) # $? == 0
vs。
local x
x=$(false) # $? == 1
但是在您的情况下,表达式
local max_loops = 4
等同于
local max_loops
local = # error, $? == 1 - an invalid name is supplied
local 4 # error, $? == 1
因此,您有一条返回状态为非零的命令。由于-errexit
的执行上下文,使用do_magic
shell标志使脚本自动退出无济于事,请参见here。
以下内容在set -e
上可以正常使用
do_magic
echo "Ran OK"
请记住,如果您依靠set -e
,请不要更改上下文。甚至以以下方式执行脚本
if ./do_magic.sh; then
:
fi
足以使set -e
魔法消失。
答案 2 :(得分:-1)
使用<string name="smth">%1$02d</string>
。
示例(t.sh):
set -e
执行:
set -e
x = r
echo hello
编辑:
您需要更改$ bash t.sh
t.sh: line 3: x: command not found
$ echo $?
127
,如下所示:
if do_magic