抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

本文转自shell 脚本里的 特殊字符 \$(( ))、\$( )、` `与\${ }的区别——马克图

在 bash 中,$( )与` `(反引号)都是用来作命令替换的

命令替换与变量替换差不多,都是用来重组命令行的,先完成引号里的命令行,然后将其结果替换出来,再重组成新的命令行
\$( )与` `
在操作上,这两者都是达到相应的效果,但是建议使用\$( ),理由如下:

` `很容易与’ '搞混乱,尤其对初学者来说,而\$( )比较直观
最后,\$( )的弊端是,并不是所有的类 unix 系统都支持这种方式,但反引号是肯定支持的。

关于命令嵌套:

1
$(ps -ef|grep `ps -ef|grep nginx |grep 'ottcache'|grep 'master process'|awk '{print $2}' ` |grep 'worker process'|awk '{print $2}')

里面的命令用 ` ` 反引号得出 pid , 再替换掉该位置,$( ) 执行另一个命令。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
echo today is $(date "+%Y-%m-%d")
today is 2019-08-14
echo today is `date "+%Y-%m-%d"`
today is 2019-08-14

echo Linux `echo Shell `echo today is `date "+%Y-%m-%d"
# 过多使用` `会有问题
Linux Shellecho today is 2017-11-07
echo Linux `echo Shell $(echo today is $(date "+%Y-%m-%d"))`
# ``和$()混合使用
Linux Shell today is 2017-11-07
echo Linux $(echo Shell $(echo today is $(date "+%Y-%m-%d")))
# 多个$()同时使用也不会有问题
Linux Shell today is 2017-11-07

${ }变量替换

一般情况下,\$var与\${var}是没有区别的,但是用${ }会比较精确的界定变量名称的范围

1
2
3
A=Linux
echo $AB #表示变量AB
echo ${A}B #表示变量A后连接着B

截取变量的部分

1
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

记忆的方法为:
 # 是去掉左边(键盘上 # 在 \$ 的左边)
 % 是去掉右边(键盘上 % 在 $ 的右边)
一个符号是最小匹配;两个符号是最大匹配

取子串及替换

命令 解释 结果
${file:0:5} 提取最左边的5个字节 /dir1
${file:5:5} 提取第5个字节右边的连续5个字节 /dir2
${file/dir/path} 将第一个dir提换为path /path1/dir2/dir3/my.file.txt
${file//dir/path} 将全部dir提换为path /path1/path2/path3/my.file.txt
${#file} 获取变量长度 27

$(( ))可以整数运算、进制转换、重定义变量值

bash中整数运算符号

符号 功能
+ - * / 分别为加、减、乘、除
% 余数运算
& | ^ ! 分别为AND、OR、XOR、NOT

e.g

1
2
3
4
5
6
7
echo $((2*3))
6
a=5;b=7;c=2
echo $((a+b*c))
19
echo $(($a+$b*$c))
19

$(( ))可以将其他进制转成十进制数显示出来

用法如下:
echo $((N#xx))
其中,N为进制,xx为该进制下某个数值,命令执行后可以得到该进制数转成十进制后的值。

1
2
3
4
5
6
echo $((2#110))
6
echo $((16#2a))
42
echo $((8#11))
9

(( ))重定义变量值,是 [ ] 数学表达式的加强版

1
2
3
4
5
6
7
8
9
10
a=5;b=7
((a++))
echo $a
6
((a--));echo $a
5
((a<b));echo $?
0
((a>b));echo $?
1

\${name[*]} \${name[@]} ${#name[*]} 区别

在 linux 的 shell 里,${name}可以表示变量,也可以表示数组。
name后面加[ ]的,一般是数组。

命令 解释
${name[*]} 数组所有元素(all of the elements)
${name[@]} 数组每一个元素(each of the elements),循环数组用这个
\${#name[*]} 数组元素的个数,也可以写成 \${#name[@]}
\${name:-Hello} 如果\${name}没有赋值,那么它等于Hello,如果赋值了,就保持原值,不用管问这个Hello了
\${!array_name[@]}、\${!array_name[*]} 获取数组下标
1
2
3
4
5
6
7
8
str="114.114.114.114 2000:192:434:234"
# 将字符串变成数组
ip_list=(${str})
for i in "${!ip_list[@]}"; do
echo "@""$i=>${ip_list[i]}""@"
done
echo "数组个数: ${#ip_list[@]}"
echo "数组下标: ${!ip_list[@]}"

单小括号 ()

命令组。括号中的命令将会新开一个子shell顺序执行,所以括号中的变量不能够被脚本余下的部分使用。括号中多个命令之间用分号隔开,最后一个命令可以没有分号,各命令和括号之间不必有空格。
命令替换。等同于`cmd`,shell扫描一遍命令行,发现了\$(cmd)结构,便将\$(cmd)中的cmd执行一次,得到其标准输出,再将此输出放到原来命令。有些shell不支持,如tcsh。
用于初始化数组。如:array=(a b c d)
($str) 会把字符串按照字段分隔符:空格、制表符、换行符,分割形成数组
注意:[[ ]] 是字符串表达式的加强版

评论