(转)linux shell中各种括号(大,中,小)

本文详细介绍了Shell脚本中括号的不同用法及其应用场景,包括小括号、中括号和大括号的多种功能,例如命令组、整数扩展、条件判断、大括号扩展等。

一、小括号,园括号()

  1、单小括号 ()

    ①命令组。括号中的命令将会新开一个子shell顺序执行,所以括号中的变量不能够被脚本余下的部分使用。括号中多个命令之间用分号隔开,最后一个命令可以没有分号,各命令和括号之间不必有空格。
    ②命令替换。等同于`cmd`,shell扫描一遍命令行,发现了$(cmd)结构,便将$(cmd)中的cmd执行一次,得到其标准输出,再将此输出放到原来命令。有些shell不支持,如tcsh。
    ③用于初始化数组。如:array=(a b c d)
 
 

  2、双小括号 ((  ))

    ①整数扩展。这种扩展计算是整数型的计算,不支持浮点型。((exp))结构扩展并计算一个算术表达式的值,如果表达式的结果为0,那么返回的退出状态码为1,或者 是"假",而一个非零值的表达式所返回的退出状态码将为0,或者是"true"。若是逻辑判断,表达式exp为真则为1,假则为0。
    ②只要括号中的运算符、表达式符合C语言运算规则,都可用在$((exp))中,甚至是三目运算符。作不同进位(如二进制、八进制、十六进制)运算时,输出结果全都自动转化成了十进制。如:echo $((16#5f)) 结果为95 (16进位转十进制)
    ③单纯用 (( )) 也可重定义变量值,比如 a=5; ((a++)) 可将 $a 重定义为6
    ④双括号中的变量可以不使用$符号前缀。括号内支持多个表达式用逗号分开。
[python]  view plain  copy
 
  1. if ($i<5)  
  2. if [ $i -lt 5 ]  
  3. if [ $a -ne 1 -a $a != 2 ]  
  4. if [ $a -ne 1] && [ $a != 2 ]  
  5. if [[ $a != 1 && $a != 2 ]]  
  6.    
  7. for i in $(seq 0 4);do echo $i;done  
  8. for i in `seq 0 4`;do echo $i;done  
  9. for ((i=0;i<5;i++));do echo $i;done  
  10. for i in {0..4};do echo $i;done  

二)中括号,方括号[]

  1、单中括号 []

    ①bash 的内部命令,[和test是等同的。如果我们不用绝对路径指明,通常我们用的都是bash自带的命令。if/test结构中的左中括号是调用test的命令标识,右中括号是关闭条件判断的。这个命令把它的参数作为比较表达式或者作为文件测试,并且根据比较的结果来返回一个退出状态码。if/test结构中并不是必须右中括号,但是新版的Bash中要求必须这样。
    ②Test和[]中可用的比较运算符只有==和!=,两者都是用于字符串比较的,不可用于整数比较,整数比较只能使用-eq,-gt这种形式。无论是字符串比较还是整数比较都不支持大于号小于号。如果实在想用,对于字符串比较可以使用转义形式,如果比较"ab"和"bc":[ ab \< bc ],结果为真,也就是返回状态为0。[ ]中的逻辑与和逻辑或使用-a 和-o 表示。
    ③字符范围。用作正则表达式的一部分,描述一个匹配的字符范围。作为test用途的中括号内不能使用正则。
    ④在一个array 结构的上下文中,中括号用来引用数组中每个元素的编号。
 
 

  2、双中括号[[ ]]

    ①[[是 bash 程序语言的关键字。并不是一个命令,[[ ]] 结构比[ ]结构更加通用。在[[和]]之间所有的字符都不会发生文件名扩展或者单词分割,但是会发生参数扩展和命令替换。
    ②支持字符串的模式匹配,使用=~操作符时甚至支持shell的正则表达式。字符串比较时可以把右边的作为一个模式,而不仅仅是一个字符串,比如[[ hello == hell? ]],结果为真。[[ ]] 中匹配字符串或通配符,不需要引号。
    ③使用[[ ... ]]条件判断结构,而不是[ ... ],能够防止脚本中的许多逻辑错误。比如,&&、||、<和> 操作符能够正常存在于[[ ]]条件判断结构中,但是如果出现在[ ]结构中的话,会报错。
    ④bash把双中括号中的表达式看作一个单独的元素,并返回一个退出状态码。

三)大括号、花括号 {}

  1、常规用法。

    ①大括号拓展。(通配(globbing))将对大括号中的文件名做扩展。在大括号中,不允许有空白,除非这个空白被引用或转义。第一种:对大括号中的以逗号分割的文件列表进行拓展。如 touch {a,b}.txt 结果为a.txt b.txt。第二种:对大括号中以点点(..)分割的顺序文件列表起拓展作用,如:touch {a..d}.txt 结果为a.txt b.txt c.txt d.txt
[python]  view plain  copy
 
  1. bogon:/home/bash # ls {ex1,ex2}.sh  
  2. ex1.sh  ex2.sh  
  3. bogon:/home/bash # ls {ex{1..3},ex4}.sh  
  4. ex1.sh  ex2.sh  ex3.sh  ex4.sh  
  5. bogon:/home/bash # ls {ex[1-3],ex4}.sh  
  6. ex1.sh  ex2.sh  ex3.sh  ex4.sh  
    ②代码块,又被称为内部组,这个结构事实上创建了一个匿名函数 。与小括号中的命令不同,大括号内的命令不会新开一个子shell运行,即脚本余下部分仍可使用括号内变量。括号内的命令间用分号隔开,最后一个也必须有分号。{}的第一个命令和左括号之间必须要有一个空格。
 
 

   2)几种特殊的替换结构:${var:-string},${var:+string},${var:=string},${var:?string}

      A,${var:-string}和${var:=string}:若变量var为空,则用在命令行中用string来替换${var:-string},否则变量var不为空时,则用变量var的值来替换${var:-string};对于${var:=string}的替换规则和${var:-string}是一样的,所不同之处是${var:=string}若var为空时,用string替换${var:=string}的同时,把string赋给变量var: ${var:=string}很常用的一种用法是,判断某个变量是否赋值,没有的话则给它赋上一个默认值。
      B. ${var:+string}的替换规则和上面的相反,即只有当var不是空的时候才替换成string,若var为空时则不替换或者说是替换成变量 var的值,即空值。(因为变量var此时为空,所以这两种说法是等价的) 
      C,${var:?string}替换规则为:若变量var不为空,则用变量var的值来替换${var:?string};若变量var为空,则把string输出到标准错误中,并从脚本中退出。我们可利用此特性来检查是否设置了变量的值。
      补充扩展:在上面这五种替换结构中string不一定是常值的,可用另外一个变量的值或是一种命令的输出。

  3)四种模式匹配替换结构${var%pattern},${var%%pattern},${var#pattern},${var##pattern}

     第一种模式:${variable%pattern},这种模式时,shell在variable中查找,看它是否一给的模式pattern结尾,如果是,就从命令行把variable中的内容去掉右边最短的匹配模式
     第二种模式: ${variable%%pattern},这种模式时,shell在variable中查找,看它是否一给的模式pattern结尾,如果是,就从命令行把variable中的内容去掉右边最长的匹配模式
     第三种模式:${variable#pattern} 这种模式时,shell在variable中查找,看它是否一给的模式pattern开始,如果是,就从命令行把variable中的内容去掉左边最短的匹配模式
     第四种模式: ${variable##pattern} 这种模式时,shell在variable中查找,看它是否一给的模式pattern结尾,如果是,就从命令行把variable中的内容去掉右边最长的匹配模式
     这四种模式中都不会改变variable的值,其中,只有在pattern中使用了*匹配符号时,%和%%,#和##才有区别。结构中的pattern支持通配符,*表示零个或多个任意字符,?表示零个或一个任意字符,[...]表示匹配中括号里面的字符,[!...]表示不匹配中括号里面的字符
[python]  view plain  copy
 
  1. bogon:/home/bash # var=testcase  
  2. bogon:/home/bash # echo $var  
  3. testcase  
  4. bogon:/home/bash # echo ${var%s*e}  
  5. testca  
  6. bogon:/home/bash # echo $var  
  7. testcase  
  8. bogon:/home/bash # echo ${var%%s*e}  
  9. te  
  10. bogon:/home/bash # echo ${var#?e}  
  11. stcase  
  12. bogon:/home/bash # echo ${var##?e}  
  13. stcase  
  14. bogon:/home/bash # echo ${var##*e}  
  15.   
  16. bogon:/home/bash # echo ${var##*s}  
  17. e  
  18. bogon:/home/bash # echo ${var##test}  
  19. case  
<think>好的,用户现在想了解Linux Shell括号转义的使用方法,特别是涉及逻辑表达式和命令嵌套的情况。首先,我需要回顾一下之前给他的回答。上一次我详细讲解了如何在`[ ]`中使用多个逻辑表达式,包括`-a`和`-o`的用法,以及常见错误和注意事项,还对比了`[ ]`和`[[ ]]`的区别。现在用户进一步询问括号转义,可能是在使用过程中遇到了问题,比如在条件判断或者命令替换时括号需要转义的情况。 用户提到可能涉及逻辑表达式或命令嵌套的场景,这意味着我需要涵盖不同括号类型的使用和转义方法,比如圆括号`()`、花括号`{}`、方括号`[]`等。首先,我应该分点讲解每种括号的作用,然后说明在哪些情况下需要转义,如何转义,并给出示例。 首先,圆括号Shell中有几个用途:子shell执行、命令替换、数组定义和算术运算。在子shell中,比如`(command)`,括号本身不需要转义,但在某些情况下,比如在`case`语句中使用括号模式匹配时,可能需要转义。在命令替换`$(...)`中,括号不需要转义,但旧式反引号中嵌套括号可能需要。算术运算`$((...))`同样不需要转义。 接下来是花括号`{}`,主要用于扩展、命令分组和函数体。在扩展时,比如`{1..3}`,不需要转义。命令分组时,如`{ cmd1; cmd2; }`,需要注意空格和分号,这里也不需要转义,除非在需要字面意义的情况下使用反斜杠转义。 方括号`[]`用于条件测试和通配符。在条件测试`[ ]`中,括号本身是test命令的一部分,内部使用逻辑运算符时需要注意空格和转义,比如使用`\( ... \)`来分组条件,但需要转义。而在`[[ ]]`中,括号是关键字,支持更多功能,比如模式匹配和正则表达式,此时括号可能不需要转义,但内部使用其他符号时可能需要。 用户可能遇到的问题包括在条件表达式中需要分组逻辑判断,这时候在`[ ]`中使用圆括号需要转义,否则会被Shell解析错误。例如,`[ \( "$a" = "yes" -a "$b" -gt 10 \) -o "$c" = "error" ]`,这里的圆括号需要反斜杠转义,并且注意空格。如果使用`[[ ]]`,则可以使用未转义括号,但需要确保语法正确。 另外,在命令嵌套时,比如在命令替换中使用括号,或者在子shell中进行管道操作,可能需要转义或者合理使用引号。例如,`echo $(echo (test))`会导致语法错误,需要改为`echo $(echo \(test\))`或者在子shell中正确使用引号。 还需要注意不同Shell版本的差异,比如Bash和Dash在括号处理上的不同。特别是在脚本的可移植性方面,使用转义可能会影响在不同Shell中的运行结果。 总结用户的需求,他们可能需要具体的例子来说明何时以及如何转义括号,尤其是在复杂的逻辑表达式和命令嵌套中。因此,我应该提供不同括号类型的转义场景,每个场景配上示例代码,并解释转义的原因和必要性。同时,对比不同括号结构(如`[ ]`和`[[ ]]`)下的处理方式,帮助用户理解何时使用转义,何时不需要。 最后,要提醒用户常见的错误,比如忘记转义导致语法错误,或者错误地使用空格,这些都可能影响脚本的执行。此外,推荐在可能的情况下使用更现代的`[[ ]]`结构,因为它更灵活且不需要频繁转义,提高代码的可读性和可靠性。</think>### Linux Shell 括号转义方法与场景解析 在 Shell 脚本中,括号(圆括号 `()`、花括号 `{}`、方括号 `[]`)的转义规则因使用场景而异,尤其是在逻辑表达式、命令嵌套或特殊符号处理中。以下是具体分类与示例: --- #### 一、圆括号 `()` 的转义场景 圆括号Shell 中主要用于 **子 Shell 执行**、**命令替换**、**数组定义** 和 **算术运算**。转义需求取决于上下文: 1. **子 Shell 执行** 子 Shell括号本身无需转义,但若需保留括号字面意义(如正则表达式),则需转义: ```bash # 子 Shell 执行(无需转义(echo "子 Shell 执行") # 正则表达式匹配(需转义) grep "\(pattern\)" file.txt ``` 2. **命令替换** 在 `$()` 中使用括号时无需转义,但旧式反引号中嵌套括号转义: ```bash # 现代写法(无需转义) result=$(echo "当前目录: $(pwd)") # 旧式反引号(需转义) result=`echo "目录: \$(pwd)"` ``` 3. **算术运算** 算术扩展 `$(( ))` 中的括号无需转义: ```bash sum=$(( 5 + (3 * 2) )) # 输出 11 ``` --- #### 二、花括号 `{}` 的转义场景 花括号用于 **扩展**、**命令分组** 或 **函数体定义**,通常无需转义,但需注意语法规则: 1. **扩展功能** ```bash # 生成序列(无需转义) echo {1..3} # 输出 1 2 3 echo {a,b,c}.txt # 输出 a.txt b.txt c.txt ``` 2. **命令分组** 花括号用于命令分组时,需注意 **空格** 和 **分号**: ```bash # 正确写法(无需转义) { echo "开始"; ls; echo "结束"; } # 错误写法(缺少分号或空格) {echo "错误示例} ``` --- #### 三、方括号 `[]` 的转义场景 方括号在 `[ ]`(条件测试)和 `[[ ]]`(Bash 扩展条件)中行为不同: 1. **条件测试 `[ ]`** 使用 `-a`(AND)、`-o`(OR)组合条件时,括号转义以调整优先级: ```bash # 检查 a > 10 且(b < 5 或 c = "yes") if [ "$a" -gt 10 -a \( "$b" -lt 5 -o "$c" = "yes" \) ]; then echo "条件满足" fi ``` **注意**: - 转义括号 `\(` 和 `\)` 表示逻辑分组。 - 括号两侧必须保留空格。 2. **Bash 扩展条件 `[[ ]]`** 支持未转义括号,且可直接使用 `&&` 和 `||`: ```bash if [[ ($num > 10 && $num < 20) || $role == "admin" ]]; then echo "条件满足" fi ``` --- #### 四、命令嵌套中的括号转义 在 **命令替换** 或 **管道嵌套** 中,括号可能需转义以避免解析歧义: 1. **嵌套命令替换** ```bash # 多层嵌套(无需转义) result=$(echo "结果: $(date)") # 旧式反引号需转义 result=`echo "日期: \`date\`"` ``` 2. **正则表达式中的括号** 在 `grep` 或 `sed` 中匹配括号时需转义: ```bash # 匹配 (example) 字符串 grep "\(example\)" file.txt sed -n 's/\(pattern\)/\1/p' file.txt ``` --- #### 五、常见错误与解决方法 | 场景 | 错误示例 | 正确写法 | 原因说明 | |-----------------------|-----------------------------|----------------------------------|---------------------------| | 条件测试中的括号优先级 | `[ $a -gt 10 -a $b -lt 5 ]` | `[ \( "$a" -gt 10 -a "$b" -lt 5 \) ]` | 未转义括号导致逻辑错误 | | 正则表达式匹配 | `grep "(pattern)" file` | `grep "\(pattern\)" file` | 括号转义,匹配失效 | | 命令替换中的嵌套 | `echo $(echo (test))` | `echo $(echo \(test\))` | 括号被解析为子 Shell 命令 | --- #### 六、总结 1. **转义原则**: - 在 `[ ]` 中调整逻辑优先级时,使用 `\( \)`。 - 正则表达式和旧式反引号命令替换中需转义括号。 - `[[ ]]` 和 `$(( ))` 等现代语法通常无需转义。 2. **推荐实践**: - 复杂逻辑优先使用 `[[ ]]` 替代 `[ ]`。 - 嵌套命令替换时使用 `$()` 而非反引号。 ```bash # 综合示例:检查文件存在且内容匹配数字 if [[ -f "data.txt" && $(grep "\([0-9]\{3\}\)" data.txt) ]]; then echo "文件存在且包含三位数字" fi ``` --- --相关问题--: 1. Shell 脚本中如何正确转义正则表达式的特殊字符(如 `*`、`?`)? 2. `[[ ]]` 和 `[ ]` 在模式匹配功能上有哪些具体差异? 3. 在 Shell 脚本中如何安全处理包含空格的变量和文件名?
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值