Shell脚本中常用的特殊符号 - 运维总结

在日常运维工作中,经常会碰到需要在一个字符串中截取我们需要的某些字符的需求,之前介绍了Shell脚本中数组的使用方法,这里介绍下基于字符串的截取的方法。在shell中截取字符串的方法有下面集中:
${var#*/}
${var##*/}
${var%/*}
${var%%/*}
${var:start:len}
${var:start}
${var:0-start:len}
${var:0-start}

可以总结为:
********************************************
#         删除最小的匹配前缀
##       删除最大的匹配前缀
%        删除最小的匹配后缀
%%     删除最大的匹配后缀
********************************************

1)获得字符串的长度
语法:${#var}   

1

2

3

4

5

6

7

8

9

10

11

12

[root@kevin~]# cat test.sh

#!/bin/bash

str="http://www.kevin.com/shibo/anhuigrace"

echo "string: [${str}]"

length=${#str}

echo "length: [${length}]"

执行结果为:

[root@kevin~]# sh test.sh

string: [http://www.kevin.com/shibo/anhuigrace]

length: [37]

2)使用 # 和 ## 获取尾部子字符串(*号在分隔符的前面,就去掉其之前的字符)
2.1) # 最小限度从前面截取word
语法:${parameter#*word} , 即截取 "第一个分隔符word及其之前的字符全部删掉"后的字符

1

2

3

4

5

6

7

8

9

10

11

12

13

[root@kevin~]# cat test.sh

#!/bin/bash

str="http://www.kevin.com/shibo/anhuigrace"

echo "string: [${str}]"

#分割符为'/'

substr=${str#*/}

echo "substr: [${substr}]"

执行结果为:

[root@kevin~]# sh test.sh

string: [http://www.kevin.com/shibo/anhuigrace]

substr: [/www.kevin.com/shibo/anhuigrace]

2.2)## 最大限度从前面截取word
语法:${parameter##*word},即截取 "最后一个分隔符word及其之前的字符全部删掉"后的字符

1

2

3

4

5

6

7

8

9

10

11

12

13

[root@kevin~]# cat test.sh 

#!/bin/bash

str="http://www.kevin.com/shibo/anhuigrace"

echo "string: [${str}]"

#分割符为'/'

substr=${str##*/}

echo "substr : [${substr}]"

执行结果为:

[root@kevin~]# sh test.sh 

string: [http://www.kevin.com/shibo/anhuigrace]

substr : [anhuigrace]

3)使用 % 和 %% 获取头部子字符串 (*在分隔符的后面,就去掉其之后的字符)
3.1)% 最小限度从后面截取word
语法:${parameter%word*},即截取 "最后一个分隔符word及其之后的字符全部删掉"后的字符

1

2

3

4

5

6

7

8

9

10

11

12

[root@kevin~]# cat test.sh

#!/bin/bash

str="http://www.kevin.com/shibo/anhuigrace"

echo "string: [${str}]"

substr=${str%/*}

echo "substr : [${substr}]"

执行结果为:

[root@kevin~]# sh test.sh

string: [http://www.kevin.com/shibo/anhuigrace]

substr : [http://www.kevin.com/shibo]

3.2)%% 最大限度从后面截取word
语法:${parameter%%*word},即截取 "第一个分隔符word及其之后的字符全部删掉"后的字符

1

2

3

4

5

6

7

8

9

10

11

12

[root@kevin~]# cat test.sh

#!/bin/bash

str="http://www.kevin.com/shibo/anhuigrace"

echo "string: [${str}]"

substr=${str%%/*}

echo "substr : [${substr}]"

执行结果为:

[root@kevin~]# sh test.sh

string: [http://www.kevin.com/shibo/anhuigrace]

substr : [http:]

4)使用 ${var:} 模式获取子字符串
4.1)指定从左边第几个字符开始以及子串中字符的个数
语法:${var:start:len}

1

2

3

4

5

6

7

8

9

10

11

12

13

[root@kevin~]# cat test.sh

#!/bin/bash

str="http://www.kevin.com/shibo/anhuigrace"

echo "string: [${str}]"

#其中的 0 表示左边第一个字符开始,7 表示子字符的总个数。

substr=${str:0:7}

echo "substr : [${substr}]"

执行结果为:

[root@kevin~]# sh test.sh

string: [http://www.kevin.com/shibo/anhuigrace]

substr : [http://]

4.2)从左边第几个字符开始一直到结束
语法:${var:7}

1

2

3

4

5

6

7

8

9

10

11

12

13

[root@kevin~]# cat test.sh

#!/bin/bash

str="http://www.kevin.com/shibo/anhuigrace"

echo "string: [${str}]"

#其中的7表示左边第8个字符开始  (如果是${str:7:5},就表示从左边第8个字符开始截取,截取5个字符)

substr=${str:7}

echo "substr : [${substr}]"

执行结果为:

[root@kevin~]# sh test.sh

string: [http://www.kevin.com/shibo/anhuigrace]

substr : [www.kevin.com/shibo/anhuigrace]

4.3)从右边第几个字符开始以及字符的个数
语法:${var:0-start:len};即${var:0-8,3} 和 ${var:2-10:3} 和 ${var:5:13:3} 是一样的,即从右边第8个开始截取,截取3个字符。 即8-0=10-2=13-5=8 

1

2

3

4

5

6

7

8

9

10

11

12

13

[root@kevin~]# cat test.sh

#!/bin/bash

str="http://www.kevin.com/shibo/anhuigrace"

echo "string: [${str}]"

#其中的 0-23 表示右边算起第23个字符开始,5 表示字符的个数

substr=${str:0-23:5}

echo "substr : [${substr}]"

执行结果为:

[root@kevin~]# sh test.sh

string: [http://www.kevin.com/shibo/anhuigrace]

substr : [in.co]

4.4)从右边第几个字符开始一直到结束
语法:${var:0-start}

1

2

3

4

5

6

7

8

9

10

11

12

13

[root@kevin~]# cat test.sh

#!/bin/bash

str="http://www.kevin.com/shibo/anhuigrace"

echo "string: [${str}]"

#其中的 0-6 表示右边算起第6个字符开始

substr=${str:0-6}

echo "substr : [${substr}]"

执行结果为:

[root@kevin~]# sh test.sh

string: [http://www.kevin.com/shibo/anhuigrace]

substr : [igrace]

####################  $( ) ${ }$(( ))的用法区别  ####################

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

一、$( ) 与 ` ` (反引号)

########################################################################################################################

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

命令替换:就是完成()或反引号里的命令行,然后将其结果替换出来,再重组命令行。

例如:

[root@ss-server ~]# echo "this is $(date +%Y-%m-%d)"

this is 2020-01-08

[root@ss-server ~]# echo "this is `date +%Y-%m-%d`" 

this is 2020-01-08

######  使用 $( ) 的理由 ######

1)` ` 反引号很容易与 ' ' 单引号搞混乱;

2)在多层次的复合替换中,` `反引号须要额外的跳脱( \` )处理,而 $( ) 则比较直观;

比如命令:command1 `command2 `command3` `

原本的意图:

是要在 command2 `command3` 中先将 command3 提换出来给 command 2 处理,然后再将结果传给 command1 `command2 …` 来处理。

然而,真正的结果:

在命令行中却是分成了 `command2 ` 与 ''两段。

小示例:

使用多层次的``反引号

[root@ss-server ~]# echo `echo `date +%Y-%m-%d``

date +%Y-%m-%d

换成 $( ) 就没问题了,做多少层的替换都没问题!

[root@ss-server ~]# echo $(echo $(date +%Y-%m-%d))

2020-01-08

###### $( ) 的不足 ######

$( ) 并不见的每一种 shell类型都能使用,如果使用 bash2 的话,肯定没问题。

二、${ } 用来作变量替换

########################################################################################################################

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

[root@ss-server ~]# a=b      

[root@ss-server ~]# echo $ab 

[root@ss-server ~]# echo ${a}b

bb

原本是打算先将 $a 的结果替换出来,然后再补一个 b 字母于其后,

但在命令行上,真正的结果却是只会提换变量名称为 ab 的值出来,结果没有ab的变量,结果就为空了!

若使用 ${ } 就没问题。

再注意区分下面的情况:即设置变量,以 = 左边的为变量名,如以右边为变量名则无效!

[root@ss-server ~]# a=b

[root@ss-server ~]# echo ${b}

[root@ss-server ~]# echo ${a} 

b

[root@ss-server ~]# echo $a b

b b

[root@ss-server ~]# echo ${a}${b}

b

[root@ss-server ~]# echo ${a}${a}

bb

[root@ss-server ~]# echo ${b}${b}

[root@ss-server ~]#

######################################################################

下面开始介绍下${ } 的一些高阶功能

先定义一个变量,下面示例都是以给变量做说明:

[root@ss-server ~]# file=/dir1/dir2/dir3/my.file.txt

1)可以用 ${ } 分别替换获得不同的值 ---------------------------

使用#和%进行截取字符串的方法在文章上面已经详细介绍了,这里就不做过多说明了。

${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

关于上面使用 # 和 % 的记忆方法为:

#  是删除掉指定字符串左边的!

%  是删除掉指定字符串右边的!

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

#*str 是删除掉第一个str及其左边的内容; ##*str 是删除掉最后一个str及其左边的内容;

%str* 是删除掉最后一个str及其右边的内容;%%str* 是删除掉第一个str及其右边的内容!

下面的截图字符串的方法在文章上面已经详细介绍了,这里就不做过多说明了。

${file:0:5}:  表示提取最左边的5个字节,即结果为:/dir1

${file:5:10}: 表示提取第5个字节右边的连续10个字节,即结果为:/dir2/dir3

如下脚本示例:

[root@bzacbsc01ap2001 ~]# hostname

bzacbsc01ap2001

主机名中第3到第6字符是本机的业务模块名称,也就是cbs。下面脚本中的表示从a字符串左边的第4个字符开始截取,截取3个字符(即3:3)

[root@bzacbsc01ap2001 ~]# cat test.sh

#!/bin/bash

a=$(hostname)

b=${a:3:3}

APP=$(echo ${b})

echo "本机tomcat的安装目录为: /opt/${APP}/tomcat"

执行结果为:

[root@bzacbsc01ap2001 ~]# sh test.sh

本机tomcat的安装目录为: /opt/cbs/tomcat

2)可以使用 ${ } 对变量值里的字符串作替换 ---------------------------

${file/dir/path}: 表示将第一个 dir 提换为 path,即结果为:/path1/dir2/dir3/my.file.txt

${file//dir/path}:表示将全部 dir 提换为 path,即结果为:/path1/path2/path3/my.file.txt

如下示例:

[root@ss-server ~]# Test_Name=kevin/bo/AnHui

[root@ss-server ~]# Test_Path=${Test_Name.}       #使用//将变量中所有的/替换为.

[root@ss-server ~]# echo ${Test_Path}

kevin.bo.AnHui

[root@ss-server ~]# Test_Path=${Test_Path/.//}        #使用/将变量中第一个.替换为/

[root@ss-server ~]# echo ${Test_Path}

kevin/bo.AnHui

[root@ss-server ~]# Test_Path=$(echo $Test_Path | tr '[A-Z]' '[a-z]')

[root@ss-server ~]# echo ${Test_Path}

kevin/bo.anhui

可以在shell脚本中进行变量的多次替换,如下:

[root@ss-server ~]# vim test.sh

#!/bin/bash

MODULE_NAME=$1

.........

# image信息

IMAGE_PATH=${MODULE_NAME.}

IMAGE_PATH=${IMAGE_PATH/.//}

IMAGE_PATH="$IMAGE_PATH.$BRANCH.$SERVICE_NAME"

IMAGE_PATH=$(echo $IMAGE_PATH | tr '[A-Z]' '[a-z]')

TAG=${REVISION:0:7}

.........

3)使用 ${ } 还可以针对不同的变量状态赋值 (没设定、空值、非空值) ---------------------------

${file-my.file.txt}:  表示假如 $file 没有设定,则使用 my.file.txt 作传回值。(空值及非空值时不作处理)

${file:-my.file.txt}: 表示假如 $file 没有设定或为空值,则使用 my.file.txt 作传回值。 (非空值时不作处理)

${file+my.file.txt}:  表示假如 $file 设为空值或非空值,均使用 my.file.txt 作传回值。(没设定时不作处理)

${file:+my.file.txt}: 表示假如 $file 为非空值,则使用 my.file.txt 作传回值。 (没设定及空值时不作处理)

${file=my.file.txt}:  表示假如 $file 没设定,则使用 my.file.txt 作传回值,同时将 $file 赋值为 my.file.txt 。 (空值及非空值时不作处理)

${file:=my.file.txt}: 表示假如 $file 没设定或为空值,则使用 my.file.txt 作传回值,同时将 $file 赋值为 my.file.txt 。 (非空值时不作处理)

${file?my.file.txt}:  表示假如 $file 没设定,则将 my.file.txt 输出至 STDERR。 (空值及非空值时不作处理)

${file:?my.file.txt}: 表示假如 $file 没设定或为空值,则将 my.file.txt 输出至 STDERR。 (非空值时不作处理)

${1:-NULL}   表示是当$1为空时,自动将NULL替换成$1所要带入的变量值。

${2:-NULL}   表示是当$2为空时,自动将NULL替换成$2所要带入的变量值。

例如:

[root@ss-server ~]# kevin=123

[root@ss-server ~]# echo ${kevin+anhui}               

anhui

[root@ss-server ~]# echo ${haha:=null}    #haha变量没有设定,则使用=后面的null作为传回值        

null

也可以在shell脚本中进行变量的状态赋值

[root@ss-server ~]# vim test.sh

#!/bin/bash

.........

AFS_ENV=${AFS_ENV:=null}

AFS_APPID=${AFS_APPID:=null}

AFS_CLUSTER=${AFS_CLUSTER:=null}

AFS_JARNAME=${AFS_JARNAME:=null}

.........

对于上面的理解,在于一定要分清楚 unset 与 null 及 non-null 这三种赋值状态。

一般而言, : 与 null 有关, 若不带 : 的话, null 不受影响, 若带 : 则连 null 也受影响!

[root@ss-server ~]# kevin=123          

[root@ss-server ~]# echo ${kevin:+anhui}

anhui

[root@ss-server ~]# kevin=

[root@ss-server ~]# echo ${kevin:+anhui}

[root@ss-server ~]# unset kevin

[root@ss-server ~]# echo ${kevin:+anhui}

[root@ss-server ~]#

使用${#var}可以计算出变量的长度

[root@ss-server ~]# echo ${file}

/dir1/dir2/dir3/my.file.txt

[root@ss-server ~]# echo ${#file}

27

三、bash的组数(array)处理方法

########################################################################################################################

一般而言,A="be sh se cho" 这样的变量只是将 $A 替换为一个单一的字符串,

但是改为 A=(be sh se cho) ,则是将 $A 定义为组数,所以说数组定义需要使用()括号!!

关于数组的使用,之前已经在 https://www.cnblogs.com/kevingrace/p/5761975.html 这篇文章中详细介绍了,这里简略说下:

组数常用的几个替换方法:

${A[@]} 或 ${A[*]}       表示获得全部组数,即得到be sh se cho 。

${A[0]}                  表示获得数组中的第1个组数。同理,${A[1]} 获得的是第2个组数。

${#A[@]} 或 ${#A[*]}     表示获得全部组数数量。

${#A[0]}                 表示获得第一个组数的长度,即be的长度,为2; 同理,${#A[3]} 表示获得第四个组数的长度,即cho的长度,为3;

A[1]=haha                 表示将第2个组数重新定义为haha; 同理,A[3]=heihei 表示将第4个组数重新定义为heihei;

四、$(( )) 用途:用来作整数运算

########################################################################################################################

在 bash 中,$(( )) 的整数运算符号大致有这些:

+ - * /    分别表示为 "加、减、乘、除"

%          表示余数运算

& | ^ !    分别表示分别为 "AND、OR、XOR、NOT" 运算。

例如:

[root@ss-server ~]# a=6;b=7;c=8

[root@ss-server ~]# echo $(( a+b*c ))

62

[root@ss-server ~]# echo $(( (a+b+3)/c ))

2

[root@ss-server ~]# echo $(( (a*b)%c))

2

使用$[]、let、$(()) 都可以作为整数运算,效果是一样的!

[root@ss-server ~]# echo $((4*9))

36

[root@ss-server ~]# echo $[4*9]

36

[root@ss-server ~]# let a=4*9

[root@ss-server ~]# echo $a

36

[root@ss-server ~]# let "a=4*9"

[root@ss-server ~]# echo $a   

36

[root@ss-server ~]# let a="3+5"  

[root@ss-server ~]# echo $a      

8

[root@ss-server ~]# a=18

[root@ss-server ~]# let a++  

[root@ss-server ~]# echo $a  

19

事实上,单纯用 (( )) 也可重定义变量值。

(( )) 这组符号的作用与 let 指令相似,用在算数运算上,是 bash 的内建功能。所以,在执行效率上会比使用 let指令要好许多。

[root@ss-server ~]# a=10; ((a++))

[root@ss-server ~]# echo ${a}

11

[root@ss-server ~]# cat test.sh

#!/bin/bash

(( a = 10 ))

echo -e "inital value, a = $a\n"

  

(( a++))

echo "after a++, a = $a"

  

[root@ss-server ~]# sh test.sh

inital value, a = 10

  

after a++, a = 11

转载于:
https://www.cnblogs.com/kevingrace/p/5896386.html

你可能感兴趣的:(c#,开发语言)