如何在“if”条件下使用圆括号

0 unix bash

我正在创建一个 bash 脚本,在里面的某个地方我有这个代码:

if [ $# -eq 2 -a (! -r "$2" -o ! -f "$2") ]; then
echo "rvf: bestand \""$2"\" bestaat niet of is onleesbaar" 1>&2
exit 2
fi
Run Code Online (Sandbox Code Playgroud)

当我尝试在脚本中运行它时,我收到此错误:

Syntax Error (bash -n):
rvf: line 14: syntax error in conditional expression
rvf: line 14: syntax error near `-a'
rvf: line 14: `if [[ $# -eq 2 -a (! -r "$2" -o ! -f "$2") ]]; then'
Run Code Online (Sandbox Code Playgroud)

'()' 如何在 Bash 脚本中工作?

che*_*ner 5

[[不支持-a,并且对于[. 使用的正确解决方案[

if [ "$#" -eq 2 ] && { [ ! -r "$2" ] || [ ! -f "$2" ]; }; then
Run Code Online (Sandbox Code Playgroud)

分组是通过{ ... }而不是( ... )为了避免创建不必要的子shell。

使用[[简化为

if [[ "$#" -eq 2 && ( ! -r "$2" || ! -f "$2" ) ]]; then
Run Code Online (Sandbox Code Playgroud)

括号可用于内部分组[[;作为一个复合命令,它使用单独的解析和评估规则,与普通命令相比[(它只是 的别名test,而不是任何类型的语法)。

无论哪种情况,德摩根定律都可以让您将其重构为更简单的内容:

if [ "$#" -eq 2 ] && ! { [ -r "$2" ] && [ -f "$2" ] }; then

if [[ "$#" -eq 2 && ! ( -r "$2" && -f "$2" ) ]]; then
Run Code Online (Sandbox Code Playgroud)

  • (在使用“[”而不是“[[”时,引用“$#”还可以防止包含数字字符的疯狂 IFS 值出现问题,因此无论如何,这都不是一个坏习惯)。 (2认同)