bash [: 大于符号的参数过多
bash [: too many arguments greater than symbol
这不是一个真正的问题(尽管我在最后提出了一个问题),而是我想分享的一个问题的解决方案,以防它对其他人有所帮助。
我在打开新终端时得到 bash: [: too many arguments
的时间最长(特别是 OS X 上安装了 bash-completion macport 的 iTerm2。此错误源自文件 /opt/local/etc/bash_completion
中的行 if [ -n "$BASH_VERSION" -a -n "$PS1" -a -z "$BASH_COMPLETION_COMPAT_DIR" ]; then
。我终于找到了问题所在,因为我的 .bash_profile
中有 export PS1='>'
。将 PS1 更改为其他内容(例如 '> '
)修复了 bash 完成的问题。
在 OS X 和 Debian 中进行的一些实验表明,在将额外的表达式(使用 -a
或 -o
)添加到测试 ([ ]
) 之后会出现此问题涉及 '>'
的表达式。例如,
> A='>'; if [ -n "$A" ]; then echo "yes"; fi
yes
> A='>'; if [ -n "$A" -a -n "$A" ]; then echo "yes"; fi
bash: [: too many arguments
> A='> '; if [ -n "$A" -o -n "$A" ]; then echo "yes"; fi
yes
> A='>'; if [ -n "$A" -o -n "Hello" ]; then echo "yes"; fi
bash: [: too many arguments
> A='>'; if [ -n "Hello" -a -n "$A" ]; then echo "yes"; fi
yes
这是 bash 中的(已知)错误吗?
如果你想使用两个或多个条件,你应该使用
if [ condition1 ] && [condition2 ]
或
if [ condition1 ] || [condition2 ]
所以在你的情况下(首先是 if "and"):
A='>'; if [ -n "$A" ] && [ -n "$A" ]; then echo "yes"; fi
对于 "or" 如果:
A='>'; if [ -n "$A" ] || [ -n "Hello" ]; then echo "yes"; fi
但请注意,第二个检查 [ -n "Hello" ]
始终为真,因此最好将其删除。
您可能对 shellcheck 感兴趣,以验证您的 bash 脚本语法。
只要 $A
中存储的字符串不是 [
/ test
识别的 运算符 ,您的解决方法就有效 -正如您所发现的,只需添加 space 就足够了。
Surely the "greater than" should be interpreted as just a string? It works with '> ' after all.
不,$A
的内容 而不是 被解释为只是一个字符串。 (如果你想要那样,你必须改用 [[
,它是在特殊的上下文中解析的,更像你对传统编程语言的期望。)
[
(test
) 是内置的(在大多数系统上也作为外部实用程序存在),因此使用 命令语法 进行解析意思是:
- shell 执行其扩展 首先 -
$A
在这种情况下,引用被替换为变量的内容。
- 然后将结果传递给
[
因此,从 [
的角度来看,它最终看到的运算符(在您的示例中为 >
)是否来自 literal[ 并不重要=78=] 或存储在 变量中 .
但请注意whitespace很重要:传递>
(没有spaces)被解释为运算符; >
,相比之下,><space>
不是 - 因为确切的文字比运算符更多。
底线是:
- 您使用的 bash-完成脚本不可靠。
- 正如@chepner 在对该问题的评论中所述,POSIX recommends not using
-o
/ -a
以避免您遇到的歧义(强调我的):
The XSI extensions specifying the -a and -o binary primaries and the '(' and ')' operators have been marked obsolescent. (Many expressions using them are ambiguously defined by the grammar depending on the specific expressions being evaluated.)
具体来说,使用单独的 [ ... ]
表达式与 &&
(而不是 -a
)和 ||
(而不是 -o
) 解决问题:
[ -n "$BASH_VERSION" ] && [ -n "$PS1" ] && [ -z "$BASH_COMPLETION_COMPAT_DIR" ]
或者,更简单地说,利用计算结果为真的非空字符串:
[ "$BASH_VERSION" ] && [ "$PS1" ] && [ -z "$BASH_COMPLETION_COMPAT_DIR" ]
请注意,虽然 -a
和 -o
引入了 歧义 ,但它们 不是 安全问题 - 你不能通过使用它们来注入任意代码。
这不是一个真正的问题(尽管我在最后提出了一个问题),而是我想分享的一个问题的解决方案,以防它对其他人有所帮助。
我在打开新终端时得到 bash: [: too many arguments
的时间最长(特别是 OS X 上安装了 bash-completion macport 的 iTerm2。此错误源自文件 /opt/local/etc/bash_completion
中的行 if [ -n "$BASH_VERSION" -a -n "$PS1" -a -z "$BASH_COMPLETION_COMPAT_DIR" ]; then
。我终于找到了问题所在,因为我的 .bash_profile
中有 export PS1='>'
。将 PS1 更改为其他内容(例如 '> '
)修复了 bash 完成的问题。
在 OS X 和 Debian 中进行的一些实验表明,在将额外的表达式(使用 -a
或 -o
)添加到测试 ([ ]
) 之后会出现此问题涉及 '>'
的表达式。例如,
> A='>'; if [ -n "$A" ]; then echo "yes"; fi
yes
> A='>'; if [ -n "$A" -a -n "$A" ]; then echo "yes"; fi
bash: [: too many arguments
> A='> '; if [ -n "$A" -o -n "$A" ]; then echo "yes"; fi
yes
> A='>'; if [ -n "$A" -o -n "Hello" ]; then echo "yes"; fi
bash: [: too many arguments
> A='>'; if [ -n "Hello" -a -n "$A" ]; then echo "yes"; fi
yes
这是 bash 中的(已知)错误吗?
如果你想使用两个或多个条件,你应该使用
if [ condition1 ] && [condition2 ]
或
if [ condition1 ] || [condition2 ]
所以在你的情况下(首先是 if "and"):
A='>'; if [ -n "$A" ] && [ -n "$A" ]; then echo "yes"; fi
对于 "or" 如果:
A='>'; if [ -n "$A" ] || [ -n "Hello" ]; then echo "yes"; fi
但请注意,第二个检查 [ -n "Hello" ]
始终为真,因此最好将其删除。
您可能对 shellcheck 感兴趣,以验证您的 bash 脚本语法。
只要 $A
中存储的字符串不是 [
/ test
识别的 运算符 ,您的解决方法就有效 -正如您所发现的,只需添加 space 就足够了。
Surely the "greater than" should be interpreted as just a string? It works with '> ' after all.
不,$A
的内容 而不是 被解释为只是一个字符串。 (如果你想要那样,你必须改用 [[
,它是在特殊的上下文中解析的,更像你对传统编程语言的期望。)
[
(test
) 是内置的(在大多数系统上也作为外部实用程序存在),因此使用 命令语法 进行解析意思是:
- shell 执行其扩展 首先 -
$A
在这种情况下,引用被替换为变量的内容。 - 然后将结果传递给
[
因此,从 [
的角度来看,它最终看到的运算符(在您的示例中为 >
)是否来自 literal[ 并不重要=78=] 或存储在 变量中 .
但请注意whitespace很重要:传递>
(没有spaces)被解释为运算符; >
,相比之下,><space>
不是 - 因为确切的文字比运算符更多。
底线是:
- 您使用的 bash-完成脚本不可靠。
- 正如@chepner 在对该问题的评论中所述,POSIX recommends not using
-o
/-a
以避免您遇到的歧义(强调我的):
The XSI extensions specifying the -a and -o binary primaries and the '(' and ')' operators have been marked obsolescent. (Many expressions using them are ambiguously defined by the grammar depending on the specific expressions being evaluated.)
具体来说,使用单独的
[ ... ]
表达式与&&
(而不是-a
)和||
(而不是-o
) 解决问题:[ -n "$BASH_VERSION" ] && [ -n "$PS1" ] && [ -z "$BASH_COMPLETION_COMPAT_DIR" ]
或者,更简单地说,利用计算结果为真的非空字符串:
[ "$BASH_VERSION" ] && [ "$PS1" ] && [ -z "$BASH_COMPLETION_COMPAT_DIR" ]
请注意,虽然 -a
和 -o
引入了 歧义 ,但它们 不是 安全问题 - 你不能通过使用它们来注入任意代码。