@@ -165,7 +165,7 @@ c*.txt
165
165
166
166
## 方括号扩展
167
167
168
- 方括号模式是 ` [...] ` ,可以匹配方括号之中的任意一个字符,比如 ` [aeiou] ` 可以匹配五个元音字母中的任意一个。该模式属于文件名匹配,即匹配后的结果必须符合现有的文件路径,如果不存在匹配,就会保持原样,不进行扩展 。
168
+ 方括号扩展的形式是 ` [...] ` ,只有文件确实存在的前提下才会扩展。如果文件不存在,就会原样输出。括号之中的任意一个字符。比如, ` [aeiou] ` 可以匹配五个元音字母中的任意一个。
169
169
170
170
``` bash
171
171
# 存在文件 a.txt 和 b.txt
@@ -175,28 +175,35 @@ a.txt b.txt
175
175
# 只存在文件 a.txt
176
176
$ ls [ab].txt
177
177
a.txt
178
+ ```
179
+
180
+ 上面例子中,` [ab] ` 可以匹配` a ` 或` b ` ,前提是确实存在相应的文件。
181
+
182
+ 方括号扩展属于文件名匹配,即扩展后的结果必须符合现有的文件路径。如果不存在匹配,就会保持原样,不进行扩展。
178
183
184
+ ``` bash
179
185
# 不存在文件 a.txt 和 b.txt
180
186
$ ls [ab].txt
181
187
ls: 无法访问' [ab].txt' : 没有那个文件或目录
182
188
```
183
189
184
- 上面命令中, ` [ab] ` 表示可以扩展成 ` a ` 或 ` b ` 。具体的执行结果,取决于当前目录是否包含指定的文件 。
190
+ 上面例子中,由于扩展后的文件不存在, ` [ab].txt ` 就原样输出了,导致 ` ls ` 命名报错 。
185
191
186
- 方括号模式还有两种变体 :` [^...] ` 和` [!...] ` 。它们表示匹配不在方括号里面的字符,这两种写法是等价的。比如,` [^abc] ` 或` [!abc] ` 表示匹配除了` a ` 、` b ` 、` c ` 以外的字符。
192
+ 方括号扩展还有两种变体 :` [^...] ` 和` [!...] ` 。它们表示匹配不在方括号里面的字符,这两种写法是等价的。比如,` [^abc] ` 或` [!abc] ` 表示匹配除了` a ` 、` b ` 、` c ` 以外的字符。
187
193
188
194
``` bash
195
+ # 存在 aaa、bbb、aba 三个文件
189
196
$ ls ? [! a]?
190
197
aba bbb
191
198
```
192
199
193
- 上面命令中,` [!a] ` 表示文件名第二个字符不是` a ` 的文件名。
200
+ 上面命令中,` [!a] ` 表示文件名第二个字符不是` a ` 的文件名,所以返回了 ` aba ` 和 ` bbb ` 两个文件 。
194
201
195
202
注意,如果需要匹配` [ ` 字符,可以放在方括号内,比如` [[aeiou] ` 。如果需要匹配连字号` - ` ,只能放在方括号内部的开头或结尾,比如` [-aeiou] ` 或` [aeiou-] ` 。
196
203
197
204
## [ start-end] 扩展
198
205
199
- 方括号模式 ` [start-end] ` 可以表示一个连续的范围 。
206
+ 方括号扩展有一个简写形式 ` [start-end] ` ,表示匹配一个连续的范围。比如, ` [a-c] ` 等同于 ` [abc] ` , ` [0-9] ` 匹配 ` [0123456789] ` 。
200
207
201
208
``` bash
202
209
# 存在文件 a.txt、b.txt 和 c.txt
@@ -213,7 +220,7 @@ report3.txt
213
220
...
214
221
```
215
222
216
- 下面是更多的例子 。
223
+ 下面是一些常用简写的例子 。
217
224
218
225
- ` [a-z] ` :所有小写字母。
219
226
- ` [a-zA-Z] ` :所有小写字母与大写字母。
@@ -222,7 +229,7 @@ report3.txt
222
229
- ` program.[co] ` :文件` program.c ` 与文件` program.o ` 。
223
230
- ` BACKUP.[0-9][0-9][0-9] ` :所有以` BACKUP. ` 开头,后面是三个数字的文件名。
224
231
225
- 方括号模式的否定形式,也可以使用连续范围的写法 ` [!start-end] ` ,表示匹配不属于这个范围的字符。比如,` [!a-zA-Z] ` 表示匹配非英文字母的字符。
232
+ 这种简写形式有一个否定形式 ` [!start-end] ` ,表示匹配不属于这个范围的字符。比如,` [!a-zA-Z] ` 表示匹配非英文字母的字符。
226
233
227
234
``` bash
228
235
$ echo report[! 1–3].txt
@@ -233,7 +240,7 @@ report4.txt report5.txt
233
240
234
241
## 大括号扩展
235
242
236
- 大括号扩展` {...} ` 表示分别输出大括号里面的所有值 ,各个值之间使用逗号分隔。这种扩展跟上面的扩展都不一样,不是文件名扩展,即不会扩展成文件名,而是扩展成所有给定的值 。
243
+ 大括号扩展` {...} ` 表示分别扩展成大括号里面的所有值 ,各个值之间使用逗号分隔。比如, ` {1,2,3} ` 扩展成 ` 1 2 3 ` 。
237
244
238
245
``` bash
239
246
$ echo {1,2,3}
@@ -246,17 +253,31 @@ $ echo Front-{A,B,C}-Back
246
253
Front-A-Back Front-B-Back Front-C-Back
247
254
```
248
255
249
- 注意,大括号内部的逗号前后不能有空格。否则,大括号模式会失效。
256
+ 注意,大括号扩展不是文件名扩展。它会扩展成所有给定的值,而不管是否有对应的文件存在。
257
+
258
+ ``` bash
259
+ $ ls {a,b,c}.txt
260
+ ls: 无法访问' a.txt' : 没有那个文件或目录
261
+ ls: 无法访问' b.txt' : 没有那个文件或目录
262
+ ls: 无法访问' c.txt' : 没有那个文件或目录
263
+ ```
264
+
265
+ 上面例子中,即使不存在对应的文件,` {a,b,c} ` 依然扩展成三个文件名,导致` ls ` 命令报了三个错误。
266
+
267
+ 另一个需要注意的地方是,大括号内部的逗号前后不能有空格。否则,大括号扩展会失效。
250
268
251
269
``` bash
252
270
$ echo {1 , 2}
253
271
{1 , 2}
254
272
```
255
273
256
- 如果逗号前面没有值,就表示扩展的第一项为空。
274
+ 上面例子中,逗号前后有空格,Bash 就会认为这不是大括号扩展,而不是两个独立的参数。
275
+
276
+ 逗号前面可以没有值,表示扩展的第一项为空。
257
277
258
278
``` bash
259
279
$ cp a.log{,.bak}
280
+
260
281
# 等同于
261
282
# cp a.log a.log.bak
262
283
```
@@ -278,16 +299,16 @@ $ echo {cat,d*}
278
299
cat dawg dg dig dog doug dug
279
300
```
280
301
281
- 上面代码中 ,会先进行大括号扩展,然后进行` * ` 扩展。
302
+ 上面例子中 ,会先进行大括号扩展,然后进行` * ` 扩展。
282
303
283
- 大括号可以用于多字符的模式,方括号不行。
304
+ 大括号可以用于多字符的模式,方括号不行(只能匹配单字符) 。
284
305
285
306
``` bash
286
307
$ echo {cat,dog}
287
308
cat dog
288
309
```
289
310
290
- 大括号模式 ` {...} ` 与方括号模式 ` [...] ` 有一个很重要的区别。如果匹配的文件不存在, ` [...] ` 会失去模式的功能,变成一个单纯的字符串,而 ` {...} ` 依然可以展开,因为大括号不是文件名扩展 。
311
+ 由于大括号扩展 ` {...} ` 不是文件名扩展,所以它总是会扩展的。这与方括号扩展 ` [...] ` 完全不同,如果匹配的文件不存在,方括号就不会扩展。这一点要注意区分 。
291
312
292
313
``` bash
293
314
# 不存在 a.txt 和 b.txt
@@ -298,19 +319,16 @@ $ echo {a,b}.txt
298
319
a.txt b.txt
299
320
```
300
321
301
- 上面代码中 ,如果不存在` a.txt ` 和` b.txt ` ,那么` [ab].txt ` 就会变成一个普通的文件名,而` {a,b}.txt ` 可以照样展开 。
322
+ 上面例子中 ,如果不存在` a.txt ` 和` b.txt ` ,那么` [ab].txt ` 就会变成一个普通的文件名,而` {a,b}.txt ` 可以照样扩展 。
302
323
303
324
## {start..end} 扩展
304
325
305
- 大括号里面两个点的 ` {start..end} ` 模式 ,表示扩展成一个连续序列,然后分别输出 。比如` {a..z} ` 可以扩展成26个小写英文字母,然后输出 。
326
+ 大括号扩展有一个简写形式 ` {start..end} ` ,表示扩展成一个连续序列。比如, ` {a..z} ` 可以扩展成26个小写英文字母。
306
327
307
328
``` bash
308
329
$ echo {a..c}
309
330
a b c
310
331
311
- $ echo {c..a}
312
- c b a
313
-
314
332
$ echo d{a..d}g
315
333
dag dbg dcg ddg
316
334
@@ -321,24 +339,24 @@ $ echo Number_{1..5}
321
339
Number_1 Number_2 Number_3 Number_4 Number_5
322
340
```
323
341
324
- 大括号的双点号支持逆序 。
342
+ 这种简写形式支持逆序 。
325
343
326
344
``` bash
345
+ $ echo {c..a}
346
+ c b a
347
+
327
348
$ echo {5..1}
328
349
5 4 3 2 1
329
-
330
- $ echo {E..A}
331
- E D C B A
332
350
```
333
351
334
- 如果遇到无法解释的扩展,模式会原样输出 。
352
+ 注意,如果遇到无法理解的简写,大括号模式就会原样输出,不会扩展 。
335
353
336
354
``` bash
337
355
$ echo {a1..3c}
338
356
{a1..3c}
339
357
```
340
358
341
- 这种模式与逗号联用,可以写出复杂的模式 。
359
+ 这种简写形式可以嵌套使用,形成复杂的扩展 。
342
360
343
361
``` bash
344
362
$ echo .{mp{3..4},m4{a,b,p,v}}
@@ -353,7 +371,18 @@ $ mkdir {2007..2009}-{01..12}
353
371
354
372
上面命令会新建36个子目录,每个子目录的名字都是”年份-月份“。
355
373
356
- 整数前面可以使用前导` 0 ` ,然后输出的每一项都有前导` 0 ` 。
374
+ 这个写法的另一个常见用途,是直接用于` for ` 循环。
375
+
376
+ ``` bash
377
+ for i in {1..4}
378
+ do
379
+ echo $i
380
+ done
381
+ ```
382
+
383
+ 上面例子会循环4次。
384
+
385
+ 如果整数前面有前导` 0 ` ,扩展输出的每一项都有前导` 0 ` 。
357
386
358
387
``` bash
359
388
$ echo {01..5}
@@ -363,7 +392,7 @@ $ echo {001..5}
363
392
001 002 003 004 005
364
393
```
365
394
366
- 大括号里面还可以使用第二个双点号 (` start..end..step ` ),用来指定扩展的步长。
395
+ 这种简写形式还可以使用第二个双点号 (` start..end..step ` ),用来指定扩展的步长。
367
396
368
397
``` bash
369
398
$ echo {0..8..2}
@@ -372,22 +401,13 @@ $ echo {0..8..2}
372
401
373
402
上面代码将` 0 ` 扩展到` 8 ` ,每次递增的长度为` 2 ` ,所以一共输出5个数字。
374
403
375
- 多个大括号连用 ,会有循环处理的效果。
404
+ 多个简写形式连用 ,会有循环处理的效果。
376
405
377
406
``` bash
378
407
$ echo {a..c}{1..3}
379
408
a1 a2 a3 b1 b2 b3 c1 c2 c3
380
409
```
381
410
382
- 这个写法可以直接用于` for ` 循环。
383
-
384
- ``` bash
385
- for i in {1..4}
386
- do
387
- echo $i
388
- done
389
- ```
390
-
391
411
## 变量扩展
392
412
393
413
Bash 将美元符号` $ ` 开头的词元视为变量,将其扩展成变量值,详见《Bash 变量》一章。
@@ -404,7 +424,7 @@ $ echo ${SHELL}
404
424
/bin/bash
405
425
```
406
426
407
- ` ${!... *} ` 或` ${!... @} ` 可以返回所有匹配的变量名 。
427
+ ` ${!string *} ` 或` ${!string @} ` 返回所有匹配给定字符串 ` string ` 的变量名 。
408
428
409
429
``` bash
410
430
$ echo ${! S* }
@@ -415,7 +435,7 @@ SECONDS SHELL SHELLOPTS SHLVL SSH_AGENT_PID SSH_AUTH_SOCK
415
435
416
436
## 子命令扩展
417
437
418
- ` $(...) ` 可以扩展成另一个命令的运行结果,内部命令的所有输出都会作为返回值 。
438
+ ` $(...) ` 可以扩展成另一个命令的运行结果,该命令的所有输出都会作为返回值 。
419
439
420
440
``` bash
421
441
$ echo $( date)
@@ -431,7 +451,7 @@ $ echo `date`
431
451
Tue Jan 28 00:01:13 CST 2020
432
452
```
433
453
434
- ` $(...) ` 还可以嵌套 ,比如` $(ls $(pwd)) ` 。
454
+ ` $(...) ` 可以嵌套 ,比如` $(ls $(pwd)) ` 。
435
455
436
456
## 算术扩展
437
457
@@ -444,7 +464,7 @@ $ echo $((2 + 2))
444
464
445
465
## 字符类
446
466
447
- ` [[:class:]] ` 表示一个字符类,匹配某一类特定字符之中的一个 。常用的字符类如下。
467
+ ` [[:class:]] ` 表示一个字符类,扩展成某一类特定字符之中的一个 。常用的字符类如下。
448
468
449
469
- ` [[:alnum:]] ` :匹配任意英文字母与数字
450
470
- ` [[:alpha:]] ` :匹配任意英文字母
@@ -475,6 +495,16 @@ $ echo [![:digit:]]*
475
495
476
496
上面命令输出所有不以数字开头的文件名。
477
497
498
+ 字符类也属于文件名扩展,如果没有匹配的文件名,字符类就会原样输出。
499
+
500
+ ` ` ` bash
501
+ # 不存在以大写字母开头的文件
502
+ $ echo [[:upper:]]*
503
+ [[:upper:]]*
504
+ ` ` `
505
+
506
+ 上面例子中,由于可匹配的文件,字符类就原样输出了。
507
+
478
508
# # 使用注意点
479
509
480
510
通配符有一些使用注意点,不可不知。
@@ -490,9 +520,9 @@ ab.txt
490
520
491
521
上面命令的执行过程是,Bash 先将` a* .txt` 扩展成` ab.txt` ,然后再执行` ls ab.txt` 。
492
522
493
- ** (2)通配符不匹配 ,会原样输出。**
523
+ ** (2)文件名扩展在不匹配时 ,会原样输出。**
494
524
495
- Bash 扩展通配符的时候,发现不存在匹配的文件,会将通配符原样输出 。
525
+ 文件名扩展在没有可匹配的文件时,会原样输出 。
496
526
497
527
` ` ` bash
498
528
# 不存在 r 开头的文件名
@@ -509,21 +539,21 @@ $ ls *.csv
509
539
ls: * .csv: No such file or directory
510
540
` ` `
511
541
512
- 另外,前面已经说过,这条规则对大括号模式 ` {...}` 不适用 。
542
+ 另外,前面已经说过,大括号扩展 ` {...}` 不是文件名扩展 。
513
543
514
544
** (3)只适用于单层路径。**
515
545
516
- 上面所有通配符只匹配单层路径 ,不能跨目录匹配,即无法匹配子目录里面的文件。或者说,` ? ` 或` * ` 这样的通配符,不能匹配路径分隔符(` /` )。
546
+ 所有文件名扩展只匹配单层路径 ,不能跨目录匹配,即无法匹配子目录里面的文件。或者说,` ? ` 或` * ` 这样的通配符,不能匹配路径分隔符(` /` )。
517
547
518
548
如果要匹配子目录里面的文件,可以写成下面这样。
519
549
520
550
` ` ` bash
521
551
$ ls * /* .txt
522
552
` ` `
523
553
524
- ** (4)可用于文件名 。**
554
+ ** (4)文件名可以使用通配符 。**
525
555
526
- Bash 允许文件名使用通配符,即文件名包括通配符字符。这时,引用文件名的时候 ,需要把文件名放在单引号里面。
556
+ Bash 允许文件名使用通配符,即文件名包括特殊字符。这时引用文件名 ,需要把文件名放在单引号里面。
527
557
528
558
` ` ` bash
529
559
$ touch ' fo*'
535
565
536
566
# # 量词语法
537
567
538
- 量词语法用来控制模式匹配的次数。它需要在 Bash 的` extglob` 参数打开的情况下,才能使用。不过,一般是默认打开的,可以用下面的命令查询 。
568
+ 量词语法用来控制模式匹配的次数。它只有在 Bash 的` extglob` 参数打开的情况下才能使用,不过一般是默认打开的。下面的命令可以查询 。
539
569
540
570
` ` ` bash
541
571
$ shopt extglob
@@ -578,11 +608,21 @@ abc.txt abc.txt.txt
578
608
579
609
上面例子中,` + (.txt)` 匹配文件有一个或多个` .txt` 后缀名。
580
610
611
+ 量词语法也属于文件名扩展,如果不存在可匹配的文件,就会原样输出。
612
+
613
+ ` ` ` bash
614
+ # 没有 abc 开头的文件名
615
+ $ ls abc? (def)
616
+ ls: 无法访问' abc?(def)' : 没有那个文件或目录
617
+ ` ` `
618
+
619
+ 上面例子中,由于没有可匹配的文件,` abc? (def)` 就原样输出,导致` ls` 命令报错。
620
+
581
621
# # shopt 命令
582
622
583
623
` shopt` 命令可以调整 Bash 的行为。它有好几个参数跟通配符扩展有关。
584
624
585
- 它的命令格式如下 。
625
+ ` shopt ` 命令的使用方法如下 。
586
626
587
627
` ` ` bash
588
628
# 打开某个参数
@@ -597,9 +637,9 @@ $ shopt [optionname]
597
637
598
638
** (1)dotglob 参数**
599
639
600
- ` dotglob` 参数可以让文件通配符包括隐藏文件 (即点开头的文件)。
640
+ ` dotglob` 参数可以让扩展结果包括隐藏文件 (即点开头的文件)。
601
641
602
- 正常情况下,通配符扩展不包括隐藏文件 。
642
+ 正常情况下,扩展结果不包括隐藏文件 。
603
643
604
644
` ` ` bash
605
645
$ ls *
@@ -651,14 +691,14 @@ bash: 无匹配: b*
651
691
652
692
** (4)extglob 参数**
653
693
654
- ` extglob` 参数使得 Bash 支持 ksh 的一些扩展语法。它默认情况下面,应该是打开的 。
694
+ ` extglob` 参数使得 Bash 支持 ksh 的一些扩展语法。它默认应该是打开的 。
655
695
656
696
` ` ` bash
657
697
$ shopt extglob
658
698
extglob on
659
699
` ` `
660
700
661
- 它的主要应用是支持量词语法。如果不希望支持 ,可以用下面的命令关闭。
701
+ 它的主要应用是支持量词语法。如果不希望支持量词语法 ,可以用下面的命令关闭。
662
702
663
703
` ` ` bash
664
704
$ shopt -u extglob
0 commit comments