1
1
# 字符串操作
2
2
3
+ 本章介绍 Bash 字符串操作的语法。
4
+
3
5
## 字符串的长度
4
6
5
7
获取字符串长度的语法如下。
@@ -11,8 +13,8 @@ ${#varname}
11
13
下面是一个例子。
12
14
13
15
``` bash
14
- $ path =/home/cam/book/long.file.name
15
- $ echo ${# path }
16
+ $ myPath =/home/cam/book/long.file.name
17
+ $ echo ${# myPath }
16
18
29
17
19
```
18
20
@@ -23,15 +25,17 @@ $ echo $#myvar
23
25
0myvar
24
26
```
25
27
28
+ 上面例子中,Bash 将` $# ` 和` myvar ` 分开解释了。
29
+
26
30
## 子字符串
27
31
28
- Bash 可以返回一个字符串的子串,语法如下 。
32
+ 字符串提取子串的语法如下 。
29
33
30
34
``` bash
31
35
${varname: offset: length}
32
36
```
33
37
34
- 上面语法的含义是返回 ` $varname ` 的子字符串,从位置` offset ` 开始(从` 0 ` 开始计算),长度为` length ` 。
38
+ 上面语法的含义是返回变量 ` $varname ` 的子字符串,从位置` offset ` 开始(从` 0 ` 开始计算),长度为` length ` 。
35
39
36
40
``` bash
37
41
$ count=frogfootman
41
45
42
46
上面例子返回字符串` frogfootman ` 从4号位置开始的长度为4的子字符串` foot ` 。
43
47
48
+ 这种语法不能直接操作字符串,只能通过变量来读取字符串,并且不会改变原始字符串。变量前面的美元符号可以省略。
49
+
50
+ ``` bash
51
+ # 报错
52
+ $ echo ${" hello" : 2: 3}
53
+ ```
54
+
55
+ 上面例子中,` "hello" ` 不是变量名,导致 Bash 报错。
56
+
44
57
如果省略` length ` ,则从位置` offset ` 开始,一直返回到字符串的结尾。
45
58
46
59
``` bash
@@ -51,7 +64,7 @@ footman
51
64
52
65
上面例子是返回变量` count ` 从4号位置一直到结尾的子字符串。
53
66
54
- 如果` offset ` 为负值,表示从字符串的末尾开始算起。注意,负数前面必须有一个空格, 以防止与` ${variable:-word} ` 的变量设置默认值的形式混淆 。这时,如果还指定` length ` ,则` length ` 不能小于零。
67
+ 如果` offset ` 为负值,表示从字符串的末尾开始算起。注意,负数前面必须有一个空格, 以防止与` ${variable:-word} ` 的变量的设置默认值语法混淆 。这时,如果还指定` length ` ,则` length ` 不能小于零。
55
68
56
69
``` bash
57
70
$ foo=" This string is long."
63
76
64
77
上面例子中,` offset ` 为` -5 ` ,表示从倒数第5个字符开始截取,所以返回` long. ` 。如果指定长度为` 2 ` ,则返回` lo ` 。
65
78
66
- 大括号里面的第一个参数,总是变量名,不能直接使用字符串。
67
-
68
- ``` bash
69
- # 报错
70
- $ echo ${" hello" : 2: 3}
71
- ```
72
-
73
- 上面例子中,` "hello" ` 不是变量名,导致 Bash 报错。
74
-
75
79
## 搜索和替换
76
80
77
- Bash 提供字符串替换的多种方法 。
81
+ Bash 提供字符串搜索和替换的多种方法 。
78
82
79
- ** (1)删除开头的匹配 。**
83
+ ** (1)字符串头部的模式匹配 。**
80
84
81
- 以下语法可以删除字符串开头匹配的部分,但不会改变原始变量 。
85
+ 以下两种语法可以检查字符串开头,是否匹配给定的模式。如果匹配成功,就删除匹配的部分,返回剩下的部分。原始变量不会发生变化 。
82
86
83
87
``` bash
84
88
# 如果 pattern 匹配变量 variable 的开头,
@@ -94,19 +98,17 @@ ${variable##pattern}
94
98
95
99
匹配模式` pattern ` 可以使用` * ` 、` ? ` 、` [] ` 等通配符。
96
100
97
- 下面是一个例子。
98
-
99
101
``` bash
100
- $ path =/home/cam/book/long.file.name
102
+ $ myPath =/home/cam/book/long.file.name
101
103
102
- $ echo ${path #/*/ }
104
+ $ echo ${myPath #/*/ }
103
105
cam/book/long.file.name
104
106
105
- $ echo ${path ##/*/ }
107
+ $ echo ${myPath ##/*/ }
106
108
long.file.name
107
109
```
108
110
109
- 上面例子中,匹配模式是 ` /*/ ` ,其中` * ` 可以匹配任意的多个字符 ,所以最短匹配是` /home/ ` ,最长匹配是` /home/cam/book/ ` 。
111
+ 上面例子中,匹配的模式是 ` /*/ ` ,其中` * ` 可以匹配任意数量的字符 ,所以最短匹配是` /home/ ` ,最长匹配是` /home/cam/book/ ` 。
110
112
111
113
下面写法可以删除文件路径的目录部分,只留下文件名。
112
114
@@ -129,9 +131,33 @@ $ echo ${phone##*-}
129
131
1414
130
132
```
131
133
132
- ** (2)删除结尾的匹配。**
134
+ 如果匹配不成功,则返回原始字符串。
135
+
136
+ ``` bash
137
+ $ phone=" 555-456-1414"
138
+ $ echo ${phone# 444}
139
+ 555-456-1414
140
+ ```
141
+
142
+ 上面例子中,原始字符串里面无法匹配模式` 444 ` ,所以原样返回。
143
+
144
+ 如果要将头部匹配的部分,替换成其他内容,采用下面的写法。
145
+
146
+ ``` bash
147
+ # 模式必须出现在字符串的开头
148
+ ${variable/# pattern/ string}
149
+
150
+ # 示例
151
+ $ foo=JPG.JPG
152
+ $ echo ${foo/# JPG/ jpg}
153
+ jpg.JPG
154
+ ```
155
+
156
+ 上面例子中,被替换的` JPG ` 必须出现在字符串头部,所以返回` jpg.JPG ` 。
133
157
134
- 以下语法可以删除字符串结尾匹配的部分,但不会改变原始变量。
158
+ ** (2)字符串尾部的模式匹配。**
159
+
160
+ 以下两种语法可以检查字符串结尾,是否匹配给定的模式。如果匹配成功,就删除匹配的部分,返回剩下的部分。原始变量不会发生变化。
135
161
136
162
``` bash
137
163
# 如果 pattern 匹配变量 variable 的结尾,
@@ -145,8 +171,6 @@ ${variable%%pattern}
145
171
146
172
上面两种语法会删除变量字符串结尾的匹配部分(将其替换为空),返回剩下的部分。区别是一个是最短匹配(又称非贪婪匹配),另一个是最长匹配(又称贪婪匹配)。
147
173
148
- 下面是一个例子。
149
-
150
174
``` bash
151
175
$ path=/home/cam/book/long.file.name
152
176
@@ -157,9 +181,9 @@ $ echo ${path%%.*}
157
181
/home/cam/book/long
158
182
```
159
183
160
- 上面例子中,匹配模式是` .* ` ,其中` * ` 可以匹配任意的多个字符 ,所以最短匹配是` .name ` ,最长匹配是` .file.name ` 。
184
+ 上面例子中,匹配模式是` .* ` ,其中` * ` 可以匹配任意数量的字符 ,所以最短匹配是` .name ` ,最长匹配是` .file.name ` 。
161
185
162
- 下面写法可以删除文件路径的文件名部分 ,只留下目录部分。
186
+ 下面写法可以删除路径的文件名部分 ,只留下目录部分。
163
187
164
188
``` bash
165
189
$ path=/home/cam/book/long.file.name
@@ -190,9 +214,25 @@ $ echo ${phone%%-*}
190
214
555
191
215
```
192
216
193
- ** (3)替换子串。 **
217
+ 如果匹配不成功,则返回原始字符串。
194
218
195
- 以下语法可以将字符串的最长匹配(贪婪匹配),换成其他的字符串返回,但不会改变原始变量。
219
+ 如果要将尾部匹配的部分,替换成其他内容,采用下面的写法。
220
+
221
+ ``` bash
222
+ # 模式必须出现在字符串的结尾
223
+ ${variable/% pattern/ string}
224
+
225
+ # 示例
226
+ $ foo=JPG.JPG
227
+ $ echo ${foo/% JPG/ jpg}
228
+ JPG.jpg
229
+ ```
230
+
231
+ 上面例子中,被替换的` JPG ` 必须出现在字符串尾部,所以返回` JPG.jpg ` 。
232
+
233
+ ** (3)任意位置的模式匹配。**
234
+
235
+ 以下两种语法可以检查字符串内部,是否匹配给定的模式。如果匹配成功,就删除匹配的部分,换成其他的字符串返回。原始变量不会发生变化。
196
236
197
237
``` bash
198
238
# 如果 pattern 匹配变量 variable 的一部分,
@@ -206,8 +246,6 @@ ${variable//pattern/string}
206
246
207
247
上面两种语法都是最长匹配(贪婪匹配)下的替换,区别是前一个语法仅仅替换第一个匹配,后一个语法替换所有匹配。
208
248
209
- 下面是一个例子。
210
-
211
249
``` bash
212
250
$ path=/home/cam/foo/foo.name
213
251
@@ -224,6 +262,10 @@ $ echo ${path//foo/bar}
224
262
225
263
``` bash
226
264
$ echo -e ${PATH//:/ ' \n' }
265
+ /usr/local/bin
266
+ /usr/bin
267
+ /bin
268
+ ...
227
269
```
228
270
229
271
上面例子中,` echo ` 命令的` -e ` 参数,表示将替换后的字符串的` \n ` 字符,解释为换行符。
@@ -249,7 +291,7 @@ $ echo ${path/.*/}
249
291
250
292
上面例子中,第二个斜杠后面的` string ` 部分省略了,所以模式` .* ` 匹配的部分` .name ` 被删除后返回。
251
293
252
- 这个语法还有两种扩展形式。
294
+ 前面提到过, 这个语法还有两种扩展形式。
253
295
254
296
``` bash
255
297
# 模式必须出现在字符串的开头
@@ -259,20 +301,6 @@ ${variable/#pattern/string}
259
301
${variable/% pattern/ string}
260
302
```
261
303
262
- 下面是一个例子。
263
-
264
- ``` bash
265
- $ foo=JPG.JPG
266
- $ echo ${foo/ JPG/ jpg}
267
- jpg.JPG
268
- $ echo ${foo// JPG/ jpg}
269
- jpg.jpg
270
- $ echo ${foo/# JPG/ jpg}
271
- jpg.JPG
272
- $ echo ${foo/% JPG/ jpg}
273
- JPG.jpg
274
- ```
275
-
276
304
## 改变大小写
277
305
278
306
下面的语法可以改变变量的大小写。
0 commit comments