编写shell过程中的小坑

Linux IT敢客 3个月前 (09-11) 1348次浏览 已收录 0个评论 扫描二维码

        经常写 shell 的朋友们应该发现,这个语言其实不是太友好,尤其是我们对于一些基本的()、(())、[]、[[]]、{}的作用和区别理解的真不是很透。下面让我们看看 shell 中各种括号()、(())、[]、[[]]、{}的作用和区别吧。

$()和 ` `  

在 bash shell 中,$( ) 与` ` (反引号) 都可用做命令替换用。

例如   

version=$(uname -r)和 version=`uname -r`都可以是 version 得到内核的版本号

各自的优缺点:
1. `  ` 基本上可用在全部的 unix shell 中使用,若写成 shell script ,其移植性比较高,但反单引号容易打错或看错。

2. $()并不是所有 shell 都支持。

${ } 

${ }用于变量替换。一般情况下,$var 与${var} 并没有什么不一样,但是用 ${ } 会比较精确的界定变量名称的范围。

例如

$ A=B
$ echo $AB
原本是打算先将 $A 的结果替换出来,然后再补一个 B 字母于其后,但在命令行上,真正的结果却是只会提换变量名称为 AB 的值出来…
若使用 ${ } 就没问题了:
$ echo ${A}B
BB

${ }的模式匹配功能:

# 是去掉左边(在键盘上#在$之左边)
% 是去掉右边(在键盘上%在$之右边)
#和%中的单一符号是最小匹配,两个相同符号是最大匹配。

${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 支持通配符,*表示零个或多个任意字符,?表示仅与一个任意字符匹配,[…]表示匹配中括号里面的字符,[!…]表示不匹配中括号里面的字符。

$[] $(()) 

$[]和$(())是一样的,都是进行数学运算的。支持+ – * / %(“加、减、乘、除、取模”)。但是注意,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 的结果
此外,$(( )) 还可作不同进位(如二进制、八进位、十六进制)运算,只是,输出结果皆为十进制而已:

echo $((16#2a)) 结果为 42 (16 进位转十进制)

[ ] 

为 test 命令的另一种形式,但要注意:
1.必须在左括号的右侧和右括号的左侧各加一个空格,否则会报错。
2.test 命令使用标准的数学比较符号来表示字符串的比较,而用文本符号来表示数值的比较

3.大于符号或小于符号必须要转义,否则会被理解成重定向。

这里做一个实验,来验证一下[]的坑:

新建一个 test.sh,内如如下:

[root@AmberHK ~]# cat test.sh 
#!/bin/bash
declare -i num
num=15
if [ $num>=15 ]; then
        echo '1';
else
        echo '0';
fi

接着我们执行这个脚本,看看输出是’1’还是’0’,结果发现是’1’,看来是可以这么用的。

[root@AmberHK ~]# sh test.sh 
1
[root@AmberHK ~]#

可是等等,别高兴的这么早,我们 ll 看一下。发现怎么多了一个=15 的文件。这个文件还是刚刚生成的!

[root@AmberHK ~]# ll
total 20
-rw-r--r-- 1 root root    0 Sep 11 17:09 =15
drwxr-xr-x 3 root root 4096 Sep  5 17:15 jumpserver
drwxr-xr-x 3 root root 4096 Aug 27 10:27 lamp
drwxr-xr-x 3 root root 4096 Aug 28 11:12 py36
-rwxr-xr-x 1 root root  100 Sep 11 17:08 test.sh
drwxr-xr-x 2 root root 4096 Aug 27 10:09 vpn
[root@AmberHK ~]# 

这里其实就有很大的问题存在了。因为=15 是脚本生成的文件,其实这里就是$num>=15 造成的。这个$num>=15 的意思是把$num 置入到文件=15 里面,所以新生成了一个=15 的文件,也就是>并没有被识别为大于号了。这里就需要做一个转义了,将$num>=15 改成$num\>=15即可。

[root@AmberHK ~]# ll
total 20
-rw-r--r-- 1 root root    0 Sep 11 17:09 =15
drwxr-xr-x 3 root root 4096 Sep  5 17:15 jumpserver
drwxr-xr-x 3 root root 4096 Aug 27 10:27 lamp
drwxr-xr-x 3 root root 4096 Aug 28 11:12 py36
-rwxr-xr-x 1 root root  101 Sep 11 17:21 test.sh
drwxr-xr-x 2 root root 4096 Aug 27 10:09 vpn
[root@AmberHK ~]# rm -rf =15
[root@AmberHK ~]# cat test.sh 
#!/bin/bash
declare -i num
num=15
if [ $num\>=15 ]; then
        echo '1';
else
        echo '0';
fi
[root@AmberHK ~]# ll
total 20
drwxr-xr-x 3 root root 4096 Sep  5 17:15 jumpserver
drwxr-xr-x 3 root root 4096 Aug 27 10:27 lamp
drwxr-xr-x 3 root root 4096 Aug 28 11:12 py36
-rwxr-xr-x 1 root root  101 Sep 11 17:21 test.sh
drwxr-xr-x 2 root root 4096 Aug 27 10:09 vpn
[root@AmberHK ~]# sh test.sh 
1
[root@AmberHK ~]# ll
total 20
drwxr-xr-x 3 root root 4096 Sep  5 17:15 jumpserver
drwxr-xr-x 3 root root 4096 Aug 27 10:27 lamp
drwxr-xr-x 3 root root 4096 Aug 28 11:12 py36
-rwxr-xr-x 1 root root  101 Sep 11 17:21 test.sh
drwxr-xr-x 2 root root 4096 Aug 27 10:09 vpn
[root@AmberHK ~]# 

这样才是正确的写法!

最后用可以下脚本的执行过程是不一样的。

[root@AmberHK ~]# sh -x test.sh 
+ declare -i num
+ num=15
+ '[' 15 ']'
+ echo 1
1
[root@AmberHK ~]# sh -x test.sh          
+ declare -i num
+ num=15
+ '[' '15>=15' ']'
+ echo 1
1
[root@AmberHK ~]# 

转义的才 15>=15,所以特别得注意。

(( ))及[[ ]] 

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

其中

[[ ]]中增加模式匹配特效;

(( ))不需要再将表达式里面的大小于符号转义,除了可以使用标准的数学运算符外,还增加了以下符号:

编写 shell 过程中的小坑


IT 敢客 , 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:编写 shell 过程中的小坑
喜欢 (3)
[313176056@qq.com]
分享 (0)
IT敢客
关于作者:
“我所做的一切都是为了方便我的生活~~~“
发表我的评论
取消评论
表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址