如何使用双括号或单括号,括号,花括号

Tim*_*Tim 637 syntax bash

我对Bash中括号,括号,花括号的用法以及它们的双重或单一形式之间的区别感到困惑.有明确的解释吗?

Pau*_*ce. 583

在Bash中,test并且[是内置的.

双托架使附加功能.例如,您可以使用&&and ||而不是-a和,-o并且有一个正则表达式匹配运算符=~.

除了分隔变量名之外,大括号还用于参数扩展,因此您可以执行以下操作:

  • 截断变量的内容

    sed
    test

  • 使替换类似于 [

    &&
    ||

  • 使用默认值

    -a
    -o

  • 还有几个

此外,大括号扩展创建字符串列表,这些字符串通常在循环中迭代:

$ time for ((i=0; i<10000000; i++)); do [[ "$i" = 1000 ]]; done

real    0m24.548s
user    0m24.337s
sys 0m0.036s
$ time for ((i=0; i<10000000; i++)); do [ "$i" = 1000 ]; done

real    0m33.478s
user    0m33.478s
sys 0m0.000s
Run Code Online (Sandbox Code Playgroud)

请注意,在Bash 4之前,前导零和增量功能不可用.

感谢gboffi提醒我关于支撑扩张的信息.

双括号用于算术运算:

$ var="abcde"; echo ${var%d*}
abc
Run Code Online (Sandbox Code Playgroud)

它们使您可以省略整数和数组变量上的美元符号,并在运算符周围包含空格以提高可读性.

单括号也用于数组索引:

$ var="abcde"; echo ${var/de/12}
abc12
Run Code Online (Sandbox Code Playgroud)

右侧(大多数/全部?)阵列参考需要使用卷曲支撑.

ephemient的评论提醒我,圆括号也用于子壳.并且它们用于创建数组.

$ default="hello"; unset var; echo ${var:-$default}
hello
Run Code Online (Sandbox Code Playgroud)

  • 警告:该功能是一个叉炸弹,不要运行它.请参阅:http://en.wikipedia.org/wiki/Fork_bomb (8认同)
  • 同样为了完整性,我只是在一个旧脚本中遇到过这个问题:`$ [expression]`; 对于较新的首选语法,这是旧的,不推荐使用的算术表达式语法:`$((expression))` (7认同)
  • 如果你用一个额外的`:`来调用它,它只是一个叉炸弹. (3认同)
  • @DennisWilliamson在'bash`中使用花括号的另一个用法是创建序列,如下面的外围提到的那样(http://stackoverflow.com/a/8552128/2749397)我想对此功能进行一些评论(因为你没有提到它;-)我冒昧地使用最多投票的答案作为载体...序列文字的两个例子:`echo {01..12}` - >`01 02 03 04 05 06 07 08 09 10 11 12`(注意最初的零); `echo {C..Q}` - >`CDEFGHIJKLMNOPQ`.它的主要用途是循环,例如`{for cnt in {01..12}; 做... $ {cnt} ...; done` (2认同)
  • @gboffi:零填充功能在 Bash 4 中可用。此外,在 Bash 4 中,您可以指定序列中的增量:`echo {01..12..2}` -&gt; "01 03 05 07 09 11" . 感谢您对序列的提醒。我会把它添加到我的答案中。 (2认同)
  • `(( ... ))` 和 `$(( ... ))` 有什么区别?添加前导“$”有什么效果? (2认同)

Car*_*rum 326

  1. 单个括号([)通常实际上调用一个名为的程序[; man testman [了解更多信息.例:

    $ VARIABLE=abcdef
    $ if [ $VARIABLE == abcdef ] ; then echo yes ; else echo no ; fi
    yes
    
    Run Code Online (Sandbox Code Playgroud)
  2. 双括号([[)与单个括号完全相同(基本上),但是内置的是bash.

    $ VARIABLE=abcdef
    $ if [[ $VARIABLE == 123456 ]] ; then echo yes ; else echo no ; fi
    no
    
    Run Code Online (Sandbox Code Playgroud)
  3. 圆括号(())用于创建子shell.例如:

    $ pwd
    /home/user 
    $ (cd /tmp; pwd)
    /tmp
    $ pwd
    /home/user
    
    Run Code Online (Sandbox Code Playgroud)

    如您所见,子shell允许您在不影响当前shell环境的情况下执行操作.

4A.大括号({})用于明确识别变量.例:

$ VARIABLE=abcdef
$ echo Variable: $VARIABLE
Variable: abcdef
$ echo Variable: $VARIABLE123456
Variable:
$ echo Variable: ${VARIABLE}123456
Variable: abcdef123456
Run Code Online (Sandbox Code Playgroud)

4B.大括号还用于在当前 shell上下文中执行一系列命令,例如

$ { date; top -b -n1 | head ; } >logfile 
# 'date' and 'top' output are concatenated, 
# could be useful sometimes to hunt for a top loader )

$ { date; make 2>&1; date; } | tee logfile
# now we can calculate the duration of a build from the logfile
Run Code Online (Sandbox Code Playgroud)

但是,有一个微妙的句法差异( )(参见bash参考); 本质上,一个分号;括号内的最后一个命令后是必须的,而括号{,} 必须用空格包围.

  • 好吧,`[`实际上是Bash内置的,但它应该像`/ bin/[`,而不是`[[`builtin.`[[`具有不同的功能,如更多逻辑操作和不同的引用角色.另外:单括号也用于数组,进程替换和扩展的globs; 双括号用于算术; 花括号`{}`用于命令分组或多种类型的参数扩展或括号扩展或序列扩展.我敢肯定我也错过了其他一些用途...... (25认同)
  • 表达式"if [$ VARIABLE == abcdef]"中的双等于是一个基础 - 尽管它有效 - 应该可以避免; 要么显式地使用bash(`if [[... == ...]]`),要么明确表示你正在使用更传统的条件(`if ["$ VARIABLE"="abcdef"]`).可以说,脚本应该尽可能简单易用,直到它们确实需要特定于bash的特性(出于某种原因).但无论如何,意图应该是明确的; "="和"=="和"[["和"["的工作方式不同,它们的用法应该是一致的. (4认同)
  • @michael_n:这句话+1.在旁注中,我喜欢编写脚本,但我觉得可靠的方法是通过`["$ var"=".."]`而不是`==`进行测试,而在C中它会分配而不是测试(并且是导致错误的常见原因)...为什么没有`test`使用`==`而不是`=`?有谁知道? (3认同)

Yol*_*ola 287

括号

if [ CONDITION ]    Test construct  
if [[ CONDITION ]]  Extended test construct  
Array[1]=element1   Array initialization  
[a-z]               Range of characters within a Regular Expression
$[ expression ]     A non-standard & obsolete version of $(( expression )) [1]
Run Code Online (Sandbox Code Playgroud)

[1] http://wiki.bash-hackers.org/scripting/obsolete

大括号

${variable}                             Parameter substitution  
${!variable}                            Indirect variable reference  
{ command1; command2; . . . commandN; } Block of code  
{string1,string2,string3,...}           Brace expansion  
{a..z}                                  Extended brace expansion  
{}                                      Text replacement, after find and xargs
Run Code Online (Sandbox Code Playgroud)

括弧

( command1; command2 )             Command group executed within a subshell  
Array=(element1 element2 element3) Array initialization  
result=$(COMMAND)                  Command substitution, new style  
>(COMMAND)                         Process substitution  
<(COMMAND)                         Process substitution 
Run Code Online (Sandbox Code Playgroud)

双括号

(( var = 78 ))            Integer arithmetic   
var=$(( 20 + 5 ))         Integer arithmetic, with variable assignment   
(( var++ ))               C-style variable increment   
(( var-- ))               C-style variable decrement   
(( var0 = var1<98?9:21 )) C-style ternary operation
Run Code Online (Sandbox Code Playgroud)

  • @MottiShneor,在您的情况下,`$(varname)` 与 bash 语法无关。它是 [Makefile 语法](//www.gnu.org/software/make/manual/html_node/Reference.html) 的一部分。 (2认同)

kzh*_*kzh 23

我只是想从TLDP添加这些:

~:$ echo $SHELL
/bin/bash

~:$ echo ${#SHELL}
9

~:$ ARRAY=(one two three)

~:$ echo ${#ARRAY}
3

~:$ echo ${TEST:-test}
test

~:$ echo $TEST


~:$ export TEST=a_string

~:$ echo ${TEST:-test}
a_string

~:$ echo ${TEST2:-$TEST}
a_string

~:$ echo $TEST2


~:$ echo ${TEST2:=$TEST}
a_string

~:$ echo $TEST2
a_string

~:$ export STRING="thisisaverylongname"

~:$ echo ${STRING:4}
isaverylongname

~:$ echo ${STRING:6:5}
avery

~:$ echo ${ARRAY[*]}
one two one three one four

~:$ echo ${ARRAY[*]#one}
two three four

~:$ echo ${ARRAY[*]#t}
one wo one hree one four

~:$ echo ${ARRAY[*]#t*}
one wo one hree one four

~:$ echo ${ARRAY[*]##t*}
one one one four

~:$ echo $STRING
thisisaverylongname

~:$ echo ${STRING%name}
thisisaverylong

~:$ echo ${STRING/name/string}
thisisaverylongstring
Run Code Online (Sandbox Code Playgroud)

  • 请注意`echo $ {#ARRAY}`显示三个,因为`ARRAY`的第一个元素包含三个字符,而不是因为它包含三个元素!要打印元素数量,请使用`echo $ {#ARRAY [@]}`. (18认同)

小智 18

测试之间的区别,[[[BashFAQ中详细解释.

简而言之:测试实现了命令的旧的可移植语法.在几乎所有的shell中(最老的Bourne shell都是例外),[是test的同义词(但需要最终参数为)).尽管所有现代shell都具有[的内置实现,但通常仍然存在该名称的外部可执行文件,例如/ bin/[.

[[是一个新的改进版本,它是一个关键字,而不是一个程序.这对易用性有益,如下所示.[[由KornShell和BASH(例如2.03)理解,但不是旧的POSIX或BourneShell.

结论是:

什么时候应该新的测试命令[[使用,当旧的[?] 如果关注BourneShell的可移植性,则应使用旧语法.另一方面,如果脚本需要BASH或KornShell,则新语法更灵活.


pab*_*ouk 18

函数定义中的括号

括号()用于函数定义:

function_name () { command1 ; command2 ; }
Run Code Online (Sandbox Code Playgroud)

这就是你必须在命令参数中转义括号的原因:

$ echo (
bash: syntax error near unexpected token `newline'

$ echo \(
(

$ echo () { command echo The command echo was redefined. ; }
$ echo anything
The command echo was redefined.
Run Code Online (Sandbox Code Playgroud)

  • @ChanKim:`unset -f echo`.见'help unset`. (2认同)