Bash Shell 各种括号的描述与例子: `() (()) [] [[]] {} ${} $() $(())`

() (()) [] [[]] {} ${} $() $(())

1.单小括号 ()

############### 单小括号 () ###############
# 1.命令组:括号中的命令将会新开一个子shell顺序执行,
#   所以括号中的变量不能够被脚本余下的部分使用。
#   括号中多个命令之间用分号隔开,最后一个命令可以没有分号,各命令和括号之间不必有空格。
(var=test;echo $var) # test
echo $var
echo --------------1\(\)

# 2.命令替换:等同于`cmd`,shell扫描一遍命令行,发现了$(cmd)结构,
#   便将$(cmd)中的cmd执行一次,得到其标准输出,再将此输出放到原来命令。
#   有些shell不支持,如tcsh。
str="love"
echo "I $(echo $str) you." # I love you.
echo "I `echo $str` you." # I love you.
echo --------------

# 3.用于初始化数组。如:array=(a b c d)
array=(a b c d)
echo "The first element of array: "$array. # The first element of array: a.
echo --------------2

2.双小括号 (())

############### 双小括号 (()) ###############
# 1.整数扩展:这种扩展计算是整数型的计算,不支持浮点型。
#   ((exp))结构扩展并计算一个算术表达式的值,如果表达式的结果为0,
#   那么返回的退出状态码为1,或者 是"假",
#   而一个非零值的表达式所返回的退出状态码将为0,或者是"true"。
#   若是逻辑判断,表达式exp为真则为1,退出状态码为0,
#   假则为0,退出状态码为1
((0+0)) # 为false
echo $? # 1
((1+0)) # 为true
echo $? # 0
((double_brackets_sum=1+0)) # 为true
echo $? # 0
echo "double_brackets_sum: "$double_brackets_sum # double_brackets_sum: 1
((1>=0))# 为true
echo $? # 0
((1<0)) # 为false
echo $? # 1
echo --------------1\(\(\)\)

# 2.只要括号中的运算符、表达式符合C语言运算规则,都可用在$((exp))中,包括三目运算符。
#   作不同进位(如二进制、八进制、十六进制、自定义进制)运算时,输出结果全都自动转化成了十进制。
#   如:echo $((16#5f)) 结果为95 (16进位转十进制)
echo $((((1<2))?2:1)) # 2
echo $((((1>2))?100:2)) # 2
echo $((16#f)) # 15
echo $((8#17)) # 15
echo $((2#1111)) # 15
echo $((3#120)) # 15
#   注意:$(())只能返回整数值,与函数返回值规则相同
# echo $((((1>2))?100:2.1)) # Err: invalid arithmetic operator (error token is ".1")
echo $((((1>2))?100:A)) # 0
# echo $((((1>2))?100:"")) # Err: operand expected (error token is """")
echo --------------2

# 3.单纯用 (()) 可重定义变量值,比如 a=5; ((a++)) 可将 $a 重定义为6
double_brackets_n=5
((double_brackets_n++))
echo $double_brackets_n # 6
echo --------------3

# 4.常用于算术运算比较,双括号中的变量可以不使用$符号前缀。
#   括号内支持多个表达式用逗号分开。
#   只要括号中的表达式符合C语言运算规,
#   比如可以直接使用for((i=0;i<5;i++)), 
#   如果不使用双括号, 则为for i in `seq 0 4`或者for i in {0..4}。
#   再如可以直接使用if (($i<5)), 如果不使用双括号, 则为if [ $i -lt 5 ]。
for((double_brackets_i=0;double_brackets_i<5;double_brackets_i++))
do
  echo $double_brackets_i # 循环输出 0 1 2 3 4
done 
if (($double_brackets_i<5))
then 
  echo "[ double_brackets_i -lt 5  ]"
else 
  echo "[ double_brackets_i -gt 5  ]" # 此行输出
fi
echo --------------4

3.单中括号 []

############### 单中括号 [] ###############
# 1.bash的内部命令,[和test是等同的。
#   如果我们不用绝对路径指明,通常我们用的都是bash自带的命令。
#   if/test结构中的左中括号是调用test的命令标识,右中括号是关闭条件判断的。
#   这个命令把它的参数作为比较表达式或者作为文件测试,并且根据比较的结果来返回一个退出状态码。
#   if/test结构中并不是必须右中括号,但是新版的Bash中要求必须这样。
type [ # [ is a shell builtin
[ 1 -gt 0 ] # 为true
echo $? # 0
test 1 -gt 0 # 为true
echo $? # 0
test 1 -gt 0 -a a=a # 为true
echo $? # 0
single_middle_n=1
test $[single_middle_n] -eq 0 # 为 false
echo $? # 1
echo --------------1\[\]

# 2.test和[]中可用的比较运算符只有=和!=,两者都是用于字符串比较的,
#   不可用于整数比较,整数比较只能使用-eq,-gt这种形式。
#   无论是字符串比较还是整数比较都不支持大于号小于号。
#   如果实在想用,对于字符串比较可以使用转义形式,
#   如果比较"ab"和"bc":[ ab \< bc ],结果为真,也就是返回状态为0。
#   [ ]中的逻辑与和逻辑或使用-a 和-o 表示。且[]前后都有空格。
[ ] # 为false
echo $? # 1
[ A = B ] # 为false
echo $? # 1
[ A=B ] # 为true,此处将A=B作为一个字符串处理
echo $? # 0
[ ab \< bc ] # 为true,此处拿两个串的单个字符unicode码自左向右逐个进行比较
echo $? # 0
[ 1 -eq 1 -a 1 -eq 0 ] # 为false
echo $? # 1
echo --------------2

# 3.字符范围:用作正则表达式的一部分,描述一个匹配的字符范围。
#   作为test用途的中括号内不能使用正则。
ls | grep ^[b].* # 输出文件名首字母为b的名称
echo --------------3

# 4.在一个array 结构的上下文中,中括号用来引用数组中每个元素的编号。
single_middle_array=(1 2)
echo ${single_middle_array[0]} # 1
single_middle_array[2]=3
echo ${single_middle_array[2]} # 3
echo --------------4

4.双中括号 [[]]

############### 双中括号 [[]] ###############
# 1.[[ 是bash程序语言的关键字,并不是一个命令,[[ ]] 结构比[ ]结构更加通用。
#   在[[和]]之间所有的字符都不会发生文件名扩展或者单词分割,但是会发生参数扩展和命令替换。

# 文件名扩展
echo {1..4}.go
# if [ {1..4}.go != "1.go 2.go 3.go 4.go" ] # Err: [: too many arguments
if [[ {1..4}.go != "1.go 2.go 3.go 4.go" ]]
then 
  echo "Yes." # 此行输出 
else
  echo "No." 
fi  

# 单词分割
double_middle_str="hello world"
# if [ $double_middle_str = "hello world" ] # Err: [: too many arguments
if [[ $double_middle_str = "hello world" ]]
then 
  echo "Yes." # 此行输出
else
  echo "No."
fi  

# 参数扩展 
function double_middle_func()
{
  # 以下命令尝试打印函数接收的第1个和第11个参数
  echo $1 $11   # 10 101
  echo $1 ${11} # 10
}
double_middle_func 10

girl=girl
echo a $girlfriend # a
echo a ${girl}friend # a girlfriend

# 命令替换
echo "I want to have a $(echo $girl)griend."
echo "I want to have a `echo $girl`griend."

function double_middle_test()
{
  double_middle_first=$1
  if [[ $11 = "$(echo $double_middle_first)1" ]]
  then 
    echo "Yes." # 此行输出
  else
    echo "No."
  fi
}
double_middle_test 10
echo --------------1\[\[\]\]

# 2.支持字符串的模式匹配,使用=~操作符时甚至支持shell的正则表达式。
#   字符串比较时可以把右边的作为一个模式,而不仅仅是一个字符串,
#   比如[[ hello == hell? ]],结果为真。
#   [[ ]] 中匹配字符串或通配符,不需要引号。
[[ "I love you." =~ ^I" "[a-z]+" "you. ]] # 为true
echo $? # 0
[[ aa = [a-z]* ]] # 为true
echo $? # 0
echo --------------2

# 3.使用[[ ... ]]条件判断结构,而不是[ ... ],能够防止脚本中的许多逻辑错误。
#   比如,&&、||、<和> 操作符能够正常存在于[[ ]]条件判断结构中,
#   但是如果出现在[ ]结构中的话,会报错。
#   比如可以直接使用if [[ $a != 1 && $a != 2 ]], 
#   如果不使用双括号, 则为if [ $a -ne 1] && [ $a != 2 ]
#   或者if [ $a -ne 1 -a $a != 2 ]。
[[ a > b ]] # 为false
echo $? # 1
[[ 10 != 1 && 10 != 2 ]] # 为true
echo $? # 0
# 以下命令等同于以上命令
[ 10 -ne 1 ] && [ 10 != 2 ] # 为true
echo $? # 0
# 以下命令等同于以上命令
[ 10 -ne 1 -a 10 != 2 ] # 为true
echo $? # 0
echo --------------3

# 4.bash把双中括号中的表达式看作一个单独的元素,并返回一个退出状态码。
[[ -b /bin/bash ]] # 为false /bin/bash 不是一个块文件
echo $? # 1
echo --------------4

5.大/花括号 {}

############### 大/花括号 {} ###############
## 1、常规用法
# 1.大括号拓展。(通配(globbing))将对大括号中的文件名做扩展。
#   在大括号中,不允许有空白,除非这个空白被引用或转义。
#   第一种:对大括号中的以逗号分割的文件列表进行拓展。
#   如 touch {a,b}.txt 结果为a.txt b.txt。
#   第二种:对大括号中以点点(..)分割的顺序文件列表起拓展作用,
#   如:touch {a..d}.txt 结果为a.txt b.txt c.txt d.txt
echo { } # { }
echo {a,b}.go # a.go b.go
echo {a..c}.go # a.go b.go c.go

# 2.代码块,又被称为内部组,这个结构事实上创建了一个匿名函数。
#   与小括号中的命令不同,大括号内的命令不会新开一个子shell运行,
#   即脚本余下部分仍可使用括号内变量。
#   括号内的命令间用分号隔开,最后一个也必须有分号。
#   {}的第一个命令和左括号之间必须要有一个空格。
#   {}也可以用于多行注释,作为函数包起来只是不调用即可。
{ big_brackets="I will be a global variable.";runtime_id=$$;}
if [ $runtime_id == $$ ]
then # 此程序块执行
  echo "Useing the same process: $$."
  echo $big_brackets
else 
  echo "Useing different process, current: $$, big_brackets runtime: $runtime_id."
fi
echo --------------1\{\}

## 2、几种特殊的替换结构 ${var:-string},${var:+string},${var:=string},${var:?string}
# 1.${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}很常用的一种用法是,
#   判断某个变量是否赋值,没有的话则给它赋上一个默认值。
echo "I "${not_def:-"love you."} # I love you.
echo $not_def # 输出空
big_brackets_hate="hate u."
echo "I "${big_brackets_hate:-"love you."} # I hate u.

echo "I "${big_brackets_runtime:="love you."} # I love you.
echo $big_brackets_runtime # love you.

# 2.${var:+string}的替换规则和上面的相反,
#   即只有当var不是空的时候才替换成string,
#   若var为空时则不替换或者说是替换成变量var的值,即空值。
#   (因为变量var此时为空,所以这两种说法是等价的)
echo "I "${big_brackets_hate:+"love you."} # I love you.
echo $big_brackets_hate # hate u.
echo "I "${not_def:+"love you."} # I

# 3.${var:?string}替换规则为:若变量var不为空,
#   则用变量var的值来替换${var:?string};
#   若变量var为空,则把string输出到标准错误中,并从脚本中退出。
#   可利用此特性来检查是否设置了变量的值。
echo "I "${big_brackets_hate:?"Something went wrong."} # I hate u.
# echo "I "${not_def:?"Something went wrong."} # Err: not_def: Something went wrong.

## 扩展:以上四种替换结构中string不一定是常值的,可用另外一个变量的值或是一种命令的输出。
echo --------------2

## 3、四种模式匹配替换结构 ${var%pattern},${var%%pattern},${var#pattern},${var##pattern}
# 模式匹配记忆方法:
# # 是去掉左边(在键盘上#在$之左边)
# % 是去掉右边(在键盘上%在$之右边)
# #和%中的单一符号是最小匹配,两个相同符号是最大匹配。
# 1. 第一种模式:${variable%pattern},这种模式时,
#   shell在variable中查找,看它是否以给的模式pattern结尾,
#   如果是,就从命令行把variable中的内容去掉右边最短的匹配模式
big_brackets_parttern1="abcabcdbcd"
big_brackets_parttern2="zabcabcdbcde"
echo ${big_brackets_parttern1%b*d} # abcabcd 
echo ${big_brackets_parttern2%b*d} # zabcabcdbcde

# 2.第二种模式: ${variable%%pattern},这种模式时,
#   shell在variable中查找,看它是否以给的模式pattern结尾,
#   如果是,就从命令行把variable中的内容去掉右边最长的匹配模式
echo ${big_brackets_parttern1%%b*d} # a 
echo ${big_brackets_parttern2%%b*d} # zabcabcdbcde

# 3.第三种模式:${variable#pattern} 这种模式时,
#   shell在variable中查找,看它是否以给的模式pattern开始,
#   如果是,就从命令行把variable中的内容去掉左边最短的匹配模式
echo ${big_brackets_parttern1#a*c} # abcdbcd
echo ${big_brackets_parttern2#a*c} # zabcabcdbcde

# 4.第四种模式: ${variable##pattern} 这种模式时,
#   shell在variable中查找,看它是否以给的模式pattern结尾,
#   如果是,就从命令行把variable中的内容去掉右边最长的匹配模式
echo ${big_brackets_parttern1##a*c} # d
echo ${big_brackets_parttern2##a*c} # zabcabcdbcde

## 扩展:这四种模式中都不会改变variable的值,其中,只有在pattern中使用了*匹配符号时,
#  %和%%,#和##才有区别。结构中的pattern支持通配符,*表示零个或多个任意字符,
#  ?表示仅与一个任意字符匹配,[...]表示匹配中括号里面的字符,
#  [!...]表示不匹配中括号里面的字符。
echo --------------3

## 4、字符串提取和替换:${var:num},${var:num1:num2},${var/pattern/pattern},${var//pattern/pattern}
# 1.第一种模式:${var:num},这种模式时,
#   shell在var中提取第num个字符到末尾的所有字符。
#   若num为正数,从左边0处开始;
#   若num为负数,从右边开始提取字串,
#   但必须使用在冒号后面加空格或一个数字或整个num加上括号,
#   如${var: -2}、${var:1-3}或${var:(-2)}。
big_brackets_string="abcdef"
echo ${big_brackets_string:2} # cdef
echo ${big_brackets_string:6} # 输出空
echo ${big_brackets_string: -2} # ef
echo ${big_brackets_string:(-2)} # ef
echo ${big_brackets_string:0-2} # ef
echo ${big_brackets_string:0-7} # 输出空

# 2.第二种模式:${var:num1:num2},num1是位置,num2是长度。
#   表示从$var字符串的第$num1个位置开始提取长度为$num2的子串。不能为负数。
echo ${big_brackets_string:2:2} # cd
echo ${big_brackets_string:2:10} # cdef
echo ${big_brackets_string:6:10} # 输出空

# 3.第三种模式:${var/pattern/pattern}
#   表示将var字符串的第一个匹配的pattern替换为另一个pattern。
echo ${big_brackets_string/abc/def} # defdef
echo ${big_brackets_string/abc/www} # wwwdef
echo ${big_brackets_string/www/www} # abcdef

# 4.第四种模式:${var//pattern/pattern}
#   表示将var字符串中的所有能匹配的pattern替换为另一个pattern。
big_brackets_string1=abbbbc
echo ${big_brackets_string1//b/w} # awwwwc
echo ${big_brackets_string1//bb/w} # awwc
echo ${big_brackets_string1//w/w} # abbbbc
echo --------------4

6.$后的括号

############### $后的括号 ###############
# 1.${variable} 变量取值,${a} 变量a的值, 在不引起歧义的情况下可以省略大括号。
echo "The environment variable value of PATH: "${PATH}

# 2.$(cmd) 命令替换,和`cmd`效果相同,
#   结果为shell命令cmd的输,某些Shell版本不支持$()形式的命令替换, 如tcsh。
echo "List of current catalog files: $(ls -al | grep ^d | awk '{printf "\n\t%s",$0}')"

# 3.$((expression)) 和`exprexpression`效果相同, 计算数学表达式exp的数值, 其中exp只要符合C语言的运算规则即可,
# 	包括三目运算符和逻辑表达式都可以计算。
dollar_after_n=$((1+2))
echo $dollar_after_n # 3
dollar_after_logic=$((1==2))
echo $dollar_after_logic # 0
echo $? # 0
# 注意$(()):还是仅支持返回整数
echo $((1 != 1?0:1)) # 1
echo $? # 0
echo $((abc == abc)) # 1
echo $((abc)) # 0
echo $(()) # 0
echo $((ls -al == ls -la)) # 1

echo --------------\$

1.Gitee:BashShell 语法学习demo源码

2.BashShell 官方手册

3.本文章作为taiyang1987912所发文章的案例补充

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值