一、 $() 与``命令的替换

  • 含义
$( )` ` 表示"命令的替换"

原理:将对反引号或$()里的内容先进行执行,然后将执行的结果代换到当前命令中
     在shell中fork一个子进程区做他们括起来的命令,然后在返回父进程

在编写脚本过程中尽量使用$( )来进行命令替换,理由如下:
🎈 ` `很容易与''搞混乱,尤其对初学者来说。
🎈 在多层次的复合替换中,` `必须要额外的转义字符处理(反斜线),而$( )比较直观。
🎈 $( )的弊端是,并不是所有的类unix系统都支持这种方式,但反引号是肯定支持的。
  • 实例
[bob@centos home]$ echo date           //直接当成字符串输出
date
[bob@centos home]$ echo `date`         //相当于函数调用,先执行date命令
Tue Sep 3 16:10:43 CST 2019
[bob@centos home]$ echo $(date)       //作用与上面的命令一样,但不是所有版本的linux系统都支持
Tue Sep 3 16:11:45 CST 2019


命令嵌套
[bob@centos home]$ echo $(echo $(date))
Tue Sep 3 16:10:43 CST 2019
[bob@centos home]$ echo `echo `date``
date
[bob@centos home]$ echo `echo \`date\``
Tue Sep 3 16:10:43 CST 2019

二、${ } 变量替换

1、含义

🎈一般情况下,$var${var}是没有区别的,但是用${ }会比较精确的界定变量名称的范围
例如:
[root@localhost ~]# A=Linux
[root@localhost ~]# echo $AB      #表示变量AB

[root@localhost ~]# echo ${A}B    #表示变量A后连接着B
LinuxB

🎈${ }内部还支持"变量替换""变量截取""变量删除"

2、变量替换

  • 变量替换含义
变量替换可以根据变量的状态(空值、非空值)来改变它的值
  • 变量替换形式
形式说明
${var}变量本来的值
${var:-word}如果变量 var 为空或已被删除(unset),那么返回 word,但不改变 var 的值。
${var:=word}如果变量 var 为空或已被删除(unset),那么返回 word,并将 var 的值设置为 word。是一种赋值默认值的常见做法
${var:?word}如果变量 var 为空或已被删除(unset),那么将消息word 送到标准错误输出,可利用此特性来检查是否设置了变量的值。若此替换出现在Shell脚本中,那么脚本将停止运行。
${var:+word}如果变量 var 被定义,那么返回 word,但不改变 var 的值。

(1)${var:-word}
若 var为空或未设置,返回默认值但是并不把默认值赋值给该变量,若 var 不为空,则不替换,var 的值不变

[Neptuneyt]$ var=
[Neptuneyt]$ echo ${var:-word}
word
[Neptuneyt]$ echo $var       #此时,变量依旧为空

(2) ${var:=word}
若var为空或未设置,把默认值赋值给该变量。若 var设置了,则不替换,var的值不变

[Neptuneyt]$ var=
[Neptuneyt]$ echo ${var:=word}
word
[Neptuneyt]$ echo $var
word

(3) ${var:+word}
若 var 不为空时,返回默认值,并且也不重新赋值。

[Neptuneyt]$ var=number
[Neptuneyt]$ echo ${net:+word}
word
[Neptuneyt]$ echo $var  #不改变变量原值
number

举个例子:

#!/bin/bash
echo "======================="
echo "  目前的版本有:  "
echo "                  mysql-8.0"
echo "                  mysql-5.7"
echo "  默认版本为: MySQL-8.0"
echo "======================="
read -p "请输入你要选择的版本"  Num
Num=`echo ${Num:=8.0}`
echo "您选择的版本为$Num,稍后给你安装......"

在这里插入图片描述

3、变量截取

指定位置截取字符串
语法:

${变量名:起始位置:长度}    从哪里截取留那里
[root@linux-server ~]# a=12345678
[root@linux-server ~]# echo ${a:5}  #从左往右第5位开始截取,留下后三位 
678
[root@linux-server ~]# echo ${a:3:4} #从第3位开始截取,留下后四位的,剩下的都不要。
4567
[root@linux-server ~]# echo ${a:2:-1} #从左往右第2位开始截取,从右往左截取第一位
34567
[root@linux-server ~]# echo ${a:2:-2}
3456

实例:

[root@localhost ~]# vim test11.sh
#!/usr/bin/bash
read -s -p "请输入您的11位手机号  " phone
echo
echo "你的手机号是 $phone"
echo "手机号后四位是 ${phone:7}"

4、匹配删除

语法:

  • #*chr 表示删除从左到右第一个遇到的字符chr及其左侧的字符
  • ##*chr表示删除从左到右最后一个遇到的字符chr及其左侧的字符(贪婪模式)
  • %chr* 表示删除从右向左第一个遇到的字符chr及其右侧的字符
  • %%chr* 表示删除从右到左最后一个遇到的字符chr及其右侧的字符(贪婪模式)

在键盘上,#在$ 符的左边,%号在$符的右边,为了便于记忆,大家因此可以记住 # 删除左边字符,%删除右边字符

参数解释:

项目Value
*表示全部字符
%最短尾匹配
%%最大尾匹配
%从右往左
#从左往右

实例:

[root@newrain ~]# echo ${url#*.}   从前往后匹配到“.”最短匹配
sina.com.cn
[root@newrain ~]# echo ${url##*.}  从前往后匹配到“.”,最长匹配
cn
[root@newrain ~]# echo ${url%.*}   从后往前匹配到“.”,最短匹配
www.sina.com
[root@newrain ~]# echo ${url%%.*}  从后往前匹配到“.”,最长匹配
www
[root@newrain ~]# echo ${url#a.}    #不加*
www.sina.com.cn
[root@newrain ~]# echo ${url#*a.}   #加*
com.cn
file=/dir1/dir2/dir3/my.file.txt
我们可以用 ${ } 分别替换获得不同的值:
${file#*/}:拿掉第一条 / 及其左边的字符串:dir1/dir2/dir3/my.file.txt
${file##*/}:拿掉最后一条 / 及其左边的字符串:my.file.txt
${file#*.}:拿掉第一个 .  及其左边的字符串:file.txt
${file##*.}:拿掉最后一个 .  及其左边的字符串:txt
${file%/*}:拿掉最后条 / 及其右边的字符串:/dir1/dir2/dir3
${file%%/*}:拿掉第一条 / 及其右边的字符串:(空值)
${file%.*}:拿掉最后一个 .  及其右边的字符串:/dir1/dir2/dir3/my.file
${file%%.*}:拿掉第一个 .  及其右边的字符串:/dir1/dir2/dir3/my

三、$ [] 与$(()) 整数运算

它们是一样的,都是进行数学运算的。支持+ - * / %:分别为 “加、减、乘、除、取模”。但是注意,bash只能作整数运算,对于浮点数是当作字符串处理的。

例:
$ a=5; b=7; c=2
$ echo $(( a+b*c ))
19
$ echo $(( (a+b)/c ))
6
$ echo $(( (a*b)%c))
1

在 $(( )) 中的变量名称,可于其前面加 $ 符号来替换,也可以不用,如:

$(( $a + $b * $c)) 
19

四、[ ] 判断符号

即为test命令的另一种形式。

单中括号 []

  • bash 的内部命令,[和test是等同的。如果我们不用绝对路径指明,通常我们用的都是bash自带的命令。if/test结构中的左中括号是调用test的命令标识,右中括号是关闭条件判断的。这个命令把它的参数作为比较表达式或者作为文件测试,并且根据比较的结果来返回一个退出状态码。if/test结构中并不是必须右中括号,但是新版的Bash中要求必须这样。

  • Test和[]中可用的比较运算符只有==和!=,两者都是用于字符串比较的,不可用于整数比较,整数比较只能使用-eq,-gt这种形式。无论是字符串比较还是整数比较都不支持大于号小于号。如果实在想用,对于字符串比较可以使用转义形式,如果比较"ab"和"bc":[ ab \ < bc ],结果为真,也就是返回状态为0。[ ]中的逻辑与和逻辑或使用-a 和-o 表示。

  • 字符范围。用作正则表达式的一部分,描述一个匹配的字符范围。作为test用途的中括号内不能使用正则。

  • 在数组中,中括号用来引用数组中每个元素的编号。下标

注意:

  1. 在括号两边各加一个空格,否则会报错。
  2. test命令使用标准的数学比较符号来表示字符串的比较,而用文本符号来表示数值的比较。(数值比较:-eq、-gt)(字符串比较:)
  3. 大于符号或小于符号必须要转义,否则会被理解成重定向。

五、(( ))与[[ ]]

它们分别是[ ]的针对数学比较表达式字符串表达式的加强版。

1、双小括号 (( ))

整数扩展。这种扩展计算是整数型的计算,不支持浮点型。((exp))结构扩展并计算一个算术表达式的值,如果表达式的结果为0,那么返回的退出状态码为1,或者 是"假",而一个非零值的表达式所返回的退出状态码将为0,或者是"true"。若是逻辑判断,表达式exp为真则为1,假则为0。

只要括号中的运算符、表达式符合C语言运算规则,都可用在$((exp))中,甚至是三目运算符。作不同进位(如二进制、八进制、十六进制)运算时,输出结果全都自动转化成了十进制。如:echo $((16#5f)) 结果为95 (16进位转十进制)

单纯用 (( )) 也可重定义变量值,比如 a=5; ((a++)) 可将 $a 重定义为6

常用于算术运算比较,双括号中的变量可以不使用 $ 符号前缀。括号内支持多个表达式用逗号分开。 只要括号中的表达式符合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 ]

2、双中括号[[ ]]

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

支持字符串的模式匹配,使用=~操作符时甚至支持shell的正则表达式。字符串比较时可以把右边的作为一个模式,而不仅仅是一个字符串,比如[[ hello == hell? ]],结果为真。[[ ]] 中匹配字符串或通配符,不需要引号。

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

bash把双中括号中的表达式看作一个单独的元素,并返回一个退出状态码。

六、()与{}的区别

相同点:

  • ()和{}都是把一串的命令放在括号里面,如果命令在一行,则命令之间用;隔开

不同点:

  • ()只是把一串命令重新开一个子shell进行执行,不影响当前shell环境;{}对一串命令在当前shell执行,影响当前shell环境
  • ()最后一个命令不用分号,{}最后一个命令要用分号
  • ()里的第一个命令和左边括号不必有空格,{}的第一个命令和左括号之间必要要有一个空格
  • ()和{}中括号里面的某个命令的重定向只影响改名了,但括号外的重定向则影响到括号里的所有命令
[root@bogon t]# var=test
[root@bogon t]# echo $var
test
[root@bogon t]# (var=notest;echo $var)
notest
[root@bogon t]# echo $var
test
[root@bogon t]# { var=notest;echo $var;}
notest
[root@bogon t]# echo $var
notest

七、==与=的区别

== 可用于判断变量是否相等,= 除了可用于判断变量是否相等外,还可以表示赋值。
= 与 == 在 [ ] 中表示判断(字符串比较)时是等价的

[root@manager day5]# s1="foo"
[root@manager day5]# s2="foo"
[root@manager day5]# [ $s1=$2 ] && echo "equal"
equal
[root@manager day5]# [ $s1==$2 ] && echo "equal"
equal

在 (( )) 中 = 表示赋值, == 表示判断(整数比较),它们不等价

[root@manager day5]# ((n=5))
[root@manager day5]# echo $n
5
[root@manager day5]# ((n==5)) && echo "equal"
equal

补充:
=~支持正则表达式,同时支持变量比较相等。==只能支持比较变量相不相等。

可知:如果需要做两个变量的包含关系,可以使用=~匹配

Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐