Linux Shell之括号语法和常用场景

0. 所谓引号

字符串符(引号)

序号 符号 作用 示例
1 ‘’ 两个单引号。单引号括住的内容,被视为常量字符串,引号内的禁止变量扩展,并且单引号字符串中不能出现单引号(对单引号使用转义符后也不行) echo '$PATH';#输出$PATH
2 “” 两个双引号。双引号包围的内容可以允许变量扩展,可以包含双引号,但需要转义。 echo "$PATH";#输出环境变量PATH的内容

1. [ expr ] 条件判断

注意[]和expr之间,必须有空格!!!可以想想test命令和expr之间的空格

等同于test expr,用于if条件判断。可以参考《Shell之if语法和常用场景》

test的三个基本作用是判断文件、判断字符串、判断整数。支持使用 ”与或非“ 将表达式连接起来。

test中可用的比较运算符只有==和!=,两者都是用于字符串比较的,不可用于整数比较,整数比较只能使用-eq, -gt这种形式。

expr, 条件表达式,都是逻辑表达式。

文件表达式

if [-d file] # 如果目录存在
if [-f file] # 如果文件存在
if [-e file] # 如果文件或目录存在
if [-x file] # 如果文件存在且为可执行文件

整数变量表达式

if [ int1 -eq int2 ]    如果int1等于int2   
if [ int1 -ne int2 ]    如果不等于    
if [ int1 -ge int2 ]       如果>=
if [ int1 -gt int2 ]       如果>
if [ int1 -le int2 ]       如果<=
if [ int1 -lt int2 ]       如果<

字符串变量表达式

If  [ $a = $b ]                 如果string1等于string2
                                字符串允许使用赋值号做等号
if  [ $string1 !=  $string2 ]   如果string1不等于string2       
if  [ -n $string  ]             如果string 非空(非0),返回0(true)  
if  [ -z $string  ]             如果string 为空
if  [ $sting ]                  如果string 非空,返回0 (和-n类似)

同样的,空格!!!!是否有空格是天壤之别,有空格是逻辑表达式,没有空格是算数表达式

[root@app17027 scripts]# if [[ 5=3 ]];then echo uuu ;else echo yyy ; fi
uuu
[root@app17027 scripts]# if [[ 5 = 3 ]];then echo uuu ;else echo yyy ; fi
yyy

[root@app17027 scripts]# if [ "sssf"="sss" ];then echo uuu ;else echo yyy ; fi
uuu
[root@app17027 scripts]# if [ "sssf" = "sss" ];then echo uuu ;else echo yyy ; fi
yyy    

2. [[ ]] 条件判断

[[]]是关键字

除了[]支持的判断外,

支持bash中的通配符扩展,如:[[ hest = h??t ]] 、[ hest = h*t ]]

支持正则匹配判断,

filelist="lvlvcheck dablelvlv checklvlv"
for file in $filelist
do 
    if [[ $file =~ lvlv$ ]]
    then
        echo $file
    fi
done

正则表达式不能使用单引号或者双引号,否则会被当做普通字符串。 如果想使Shell if不匹配指定的正则表达式,可以使用Shell的逻辑非运算符感叹号!

if [[ ! $file =~ check$ ]]

虽然[[]]支持除了gt,eq那些外,也支持+ - * /运算符,但是最好不要用,实在想用,就用(())。

使用 (( )) 时,不需要空格分隔各值和运算符,使用 [[ ]] 时需要用空格分隔各值和运算符。

3. ()

一般用于表达式的分隔。

有个有意思的,可以用于定义数组。然后通过${}来取数组里的值。

A="a b c def"   # 定义字符串
A=(a b c def)   # 定义字符数组
#字符串的话,没法取
[root@app17027 scripts]# A="a b c d e f"
[root@app17027 scripts]# echo ${A[0]}
a b c d e f
#数组的话,可以取指定序号的变量值

4. (( )) 算数计算

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

只能用于整数计算。不能用于浮点数。

+加 -减 *乘 /除 %取余数 &与 |或 ^ !非

5. $() 命令替换

等同于反引号` 。$( )的弊端是,并不是所有的类unix系统都支持这种方式,但反引号是肯定支持的。

先完成命令执行,将其结果替换出来,组成新的命令行。

这个原理简单,但是命令执行的结果,很有意思。

要区分命令执行的结果和exit状态码。

exit状态码通过$?来获取上一个命令执行的exit状态码。

命令执行结果一般是stdout打印出来的。

[root@app17027 scripts]# cat printOSVersion.sh 
cat /etc/redhat-release
exit 1
[root@app17027 scripts]# aaa=`./printOSVersion.sh`
[root@app17027 scripts]# echo $?
1
[root@app17027 scripts]# echo $aaa
CentOS release 6.8 (Final)

6. $(()) 返回算数计算的结果

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

各种进制转换为十进制

[root@app17027 scripts]# if [ $((16#ff)) -gt $((16#bb)) ];then echo uuu ;else echo yyy ; fi
uuu

{}

{{}}

7. ${}

7.1. 变量

${var}与$var等同。但是,如果$AB和${A}B是不一样的。。。

[root@localhost ~]# A=Linux
[root@localhost ~]# echo $AB    #表示变量AB

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

7.2. 字符串命令

先赋值一个变量为一个路径,如下:
file=/dir1/dir2/dir3/my.file.txt

以下样例全部以这个file为字符串。

7.2.1. 取子串

${file::}

从index开始(包括index位置的字符),length个字符。注意,index从0开始。

命令 解释 结果
${file:0:5} 提取最左边的 5 个字节 /dir1
${file:5:5} 提取第 5 个字节右边的连续 5 个字节 /dir2
${#file} 获取变量长度 27

7.2.2. 字符替换

${file/src/dest} # 只替换第一个匹配
${file//src/dest} # 全部替换
命令 解释 结果
${file/dir/path} 将第一个 dir 替换为 path /path1/dir2/dir3/my.file.txt
${file//dir/path} 将全部 dir 替换为 path /path1/path2/path3/my.file.txt

7.2.3. 取路径、文件名、后缀

# 是去掉左边(在键盘上 # 在 $ 之左边)

% 是去掉右边(在键盘上 % 在 $ 之右边)

单一符号是最小匹配,两个符号是最大匹配

*是用来匹配不要的字符,也就是想要去掉的那部分

还有指定字符分隔号,与*配合,决定取哪部分

命令    解释    结果
${file#*/}    拿掉第一条 / 及其左边的字符串    dir1/dir2/dir3/my.file.txt
[root@localhost ~]# echo ${file#*/}
dir1/dir2/dir3/my.file.txt

${file##*/}    拿掉最后一条 / 及其左边的字符串    my.file.txt
[root@localhost ~]# echo ${file##*/}
my.file.txt

${file#*.}    拿掉第一个 . 及其左边的字符串    file.txt
[root@localhost ~]# echo ${file#*.}
file.txt

${file##*.}    拿掉最后一个 . 及其左边的字符串    txt
[root@localhost ~]# echo ${file##*.}
txt

${file%/*}    拿掉最后一条 / 及其右边的字符串    /dir1/dir2/dir3
[root@localhost ~]# echo ${file%/*}
/dir1/dir2/dir3

${file%%/*}    拿掉第一条 / 及其右边的字符串    (空值)
[root@localhost ~]# echo ${file%%/*}
(空值)

${file%.*}    拿掉最后一个 . 及其右边的字符串    /dir1/dir2/dir3/my.file
[root@localhost ~]# echo ${file%.*}
/dir1/dir2/dir3/my.file

${file%%.*}    拿掉第一个 . 及其右边的字符串    /dir1/dir2/dir3/my
[root@localhost ~]# echo ${file%%.*}
/dir1/dir2/dir3/my

还有好玩的命令

获取文件绝对路径 
$(readlink -f $f)

$ dirname ‘/home/lalor/a.txt'
/home/lalor
$ basename ‘/home/lalor/a.txt'
a.txt

7.3. 数组命令

命令 解释 结果
${A[@]} 返回数组全部元素 a b c def
${A[*]} 同上 a b c def
${A[0]} 返回数组第一个元素 a
${#A[@]} 返回数组元素总个数 4
${#A[*]} 同上 4
${#A[3]} 返回第四个元素的长度,即def的长度 3
A[3]=xzy 则是将第四个组数重新定义为 xyz

8. ${{}}

没有这个。

9. 关于和if的搭配

if condition

这个condition,有意思。

  • 最常见的是 []和[[]],

  • 但是也可以有command,这里condition就是command的exit状态码,而不是命令执行结果,

  • 再一个是(())算数表达式,这个表达式一般看成逻辑表达式。而且不用加$为$(())

    [root@app17027 scripts]# if $(( 5 > 3 )) ;then echo uuu ; else echo yyy; fi
    -bash: 1: command not found
    yyy

10. 是command还是expr

关于(()),到底看成command还是expr,呵呵。

[root@app17027 scripts]# (( 5 < 3 ))
[root@app17027 scripts]# echo $?
1
[root@app17027 scripts]# (( 5 > 3 ))
[root@app17027 scripts]# echo $?
0

[root@app17027 scripts]# [ 5 -gt 3 ]
[root@app17027 scripts]# echo $?
0
[root@app17027 scripts]# [ 5 -gt 9 ]
[root@app17027 scripts]# echo $?
1    


[root@app17027 scripts]# bbb = [ 5 -gt 9 ]
-bash: bbb: command not found
[root@app17027 scripts]# bbb=[ 5 -gt 9 ]
-bash: 5: command not found    

[root@app17027 scripts]# ccc = (( 5 > 3 ))
-bash: syntax error near unexpected token `('
[root@app17027 scripts]# ccc=$(( 5 > 3 ))    

参考链接

https://www.cnblogs.com/chengd/p/7803664.html

http://c.biancheng.net/view/2480.html

https://blog.csdn.net/sunxiaopengsun/article/details/82656059

https://blog.csdn.net/K346K346/article/details/51819236

你可能感兴趣的:(Linux Shell之括号语法和常用场景)