我有一个函数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
}
答案 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
仅在输出到终端时启动的内容。
你可以
更改别名以使用--colour=auto
:
alias grep='grep -EI --colour=auto'
或
使用\grep
:
curr_ver=$(emacs --version | \grep -oE '[[:digit:]]+\.[.[:digit:]]*')
--colour
有效的原因是因为没有参数,它默认为--colour=auto
(http://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;