为什么“24> 10#24”会生成错误令牌?

时间:2014-04-24 07:28:49

标签: bash

我有一个函数vercomp,它比较两个版本字符串并确定哪一个更大。当我添加这个别名时:

alias grep='grep -EI --colour=always'

到我的bashrc文件看似无关的部分我收到此错误:

-bash: 10#24 > 10#24: syntax error: invalid arithmetic operator (error token is "24 > 10#24")
-bash: 10#24 < 10#24: syntax error: invalid arithmetic operator (error token is "24 < 10#24")

请注意,错误会被发出两次,我假设是因为错误被处理了两次(即这不是我的错误)。请注意,当我删除别名时,一切正常。 为什么会生成此错误以及如何缓解此错误?

以下感兴趣的行可能是标记为:

的行
    if ((10#${ver1[i]} > 10#${ver2[i]})); then
        return 1
    fi
    if ((10#${ver1[i]} < 10#${ver2[i]})); then
        return 2
    fi

编辑:添加更多上下文

我在Mac OS X 10.7.5(Lion)上使用GNU bash, version 3.2.48(1)-release (x86_64-apple-darwin11)。我这样打电话给vercomp

if [[ $OS = 'Mac' ]]; then                                                                                                                                                                                 
    ### EMACS VERSION CHECK                                                                                                                                                                                
    # make sure that we're working with emacs >= 24                                                                                                                                                        
    wanted_ver=24                                                                                                                                                                                          
    curr_ver=`emacs --version | grep -oE '[[:digit:]]+\.[.[:digit:]]*'`                                                                                                                                    
    echo $curr_ver                                                                                                                                                                                         
    vercomp $curr_ver $wanted_ver

请注意,我正在呼叫grep初始化curr_ver。我仍然无法弄清楚错误发生的原因,但使用grep -EI --colour并不会产生错误,因此我会回答问题的第二部分。有谁知道为什么错误发生了?


vercomp () {
    ## returns: 0 equal
    ##          1 ver1 > ver 2
    ##          2 ver1 < ver 2
    if [[ $1 == $2 ]]; then
        return 0
    fi

    # IFS (Internal Field Separator) Fields are separated by a '.'
    # ($var) notation means turn $var into an array according to the IFS.
    local IFS=.
    local i ver1=($1) ver2=($2)

    # fill empty fields in ver1 with zeros
    # ${#var[@]} = the number of elements in the array/var.
    for ((i=${#ver1[@]}; i<${#ver2[@]}; i++)); do
        ver1[i]=0
    done
    for ((i=0; i<${#ver1[@]}; i++)); do
        if [[ -z ${ver2[i]} ]]; then
            # fill empty fields in ver2 with zeros
            ver2[i]=0
        fi
        # <num>#$var converts the value of $var to the base of <num>
        if ((10#${ver1[i]} > 10#${ver2[i]})); then
            return 1
        fi
        if ((10#${ver1[i]} < 10#${ver2[i]})); then
            return 2
        fi
    done
    return 0
}

2 个答案:

答案 0 :(得分:4)

使用别名grep生成您传递给vercomp的两个变量中的任何一个,您几乎肯定会发现在生成的输出中有转义序列。

这是因为根据grep手册页明确告诉 --color=ALL使用grep执行此操作:

  

- color [= WHEN] :环绕匹配的(非空)字符串,匹配行,上下文行,文件名,行号,字节偏移和分隔符(对于字段和组)具有转义序列的上下文行)在终端上以彩色显示它们。

如果您输入以下代码,这将变得明显:

echo "$1" | od -xcb
echo "$2" | od -xcb

在您的vercomp功能开始时。在这种情况下,逃逸序列应该很容易被发现。

事实上,如果我在一个包含vercomp函数的脚本中执行以下代码:

curr_ver=$(echo 21.7 | grep -EI --color=always '^..')
echo "$curr_ver" | od -xcb
vercomp $curr_ver 21.5

输出是:

0000000    5b1b    3130    333b    6d31    5b1b    324b    1b31    6d5b
        033   [   0   1   ;   3   1   m 033   [   K   2   1 033   [   m
        033 133 060 061 073 063 061 155 033 133 113 062 061 033 133 155
0000020    5b1b    2e4b    0a37
        033   [   K   .   7  \n
        033 133 113 056 067 012
0000026
./qq.bash: line 30: 10#21 > 10#21: syntax error: invalid arithmetic
    operator (error token is "21 > 10#21")
./qq.bash: line 33: 10#21 < 10#21: syntax error: invalid arithmetic
    operator (error token is "21 < 10#21")

所以你可以看到两个:

  • 输出中有转义序列,以便为找到的术语着色;和
  • 它会产生与您所看到的类似的错误。

如果你摆脱了色彩(即使只是暂时的),你会发现错误消失了。

答案 1 :(得分:2)

这就是为什么你不应该将grep别名变为grep --colour=always,它确实完全按照你要求它使用ANSI转义码在管道中进行stdout。 这就是grep --colour=auto仅在输出到终端时启动的内容。

你可以

  1. 更改别名以使用--colour=auto

    alias grep='grep -EI --colour=auto'

  2. 使用\grep

    绕过别名

    curr_ver=$(emacs --version | \grep -oE '[[:digit:]]+\.[.[:digit:]]*')

  3. --colour有效的原因是因为没有参数,它默认为--colour=autohttp://git.savannah.gnu.org/cgit/grep.git/tree/src/grep.c):

    case COLOR_OPTION:
            if (optarg)
              {
                if (!strcasecmp (optarg, "always") || !strcasecmp (optarg, "yes")
                    || !strcasecmp (optarg, "force"))
                  color_option = 1;
                else if (!strcasecmp (optarg, "never") || !strcasecmp (optarg, "no")
                         || !strcasecmp (optarg, "none"))
                  color_option = 0;
                else if (!strcasecmp (optarg, "auto") || !strcasecmp (optarg, "tty")
                         || !strcasecmp (optarg, "if-tty"))
                  color_option = 2;
                else
                  show_help = 1;
              }
            else
              color_option = 2;    # <--- HERE: default to 2 (auto)
            break;