如果语法错误

时间:2017-12-12 11:38:52

标签: bash error-handling

我最近对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

我的问题:是否有任何通用方法可以说未处理错误的函数返回非零值?

我已在此修复了实际错误,但我希望让脚本更强大。

3 个答案:

答案 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