Skip to content

Commit 0ad2781

Browse files
committed
docs: edit expansion
1 parent 76c190a commit 0ad2781

6 files changed

Lines changed: 139 additions & 72 deletions

File tree

Lines changed: 84 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,55 @@
1-
# Bash 的通配符
1+
# Bash 的扩展模式
22

33
Shell 接收到用户输入的命令以后,会根据空格将用户的输入,拆分成一个个词元(token)。然后,Shell 会扩展词元里面的特殊字符,扩展完成后才会调用相应的命令。
44

5-
Shell 的命令扩展一共有八种
5+
这种特殊字符的扩展,称为通配符扩展(wildcard expansion)或者模式扩展(globbing)。Bash 一共提供八种扩展,先进行扩展,然后再执行命令
66

7-
Bash 提供通配符(wildcards),用一种很短的文本模式(通常只有一个字符),简洁地代表一组路径。Bash 在执行命令之前,会自动扩展命令中的通配符
7+
早期的 Unix 系统有一个`/etc/glob`文件,保存扩展的模板。后来 Bash 内置了这个功能,但是这个名字保留了下来。特殊字符的扩展早于正则表达式出现,可以看作是原始的正则表达式。它的功能没有正则那么强大灵活,但是优点是简单和方便
88

9-
通配符又叫做 globbing patterns。因为 Unix 早期有一个`/etc/glob`文件保存通配符模板,后来 Bash 内置了这个功能,但是这个名字被保留了下来。
9+
## 波浪线扩展
10+
11+
波浪线`~`会自动扩展成当前用户的主目录。
12+
13+
```bash
14+
$ echo ~
15+
/home/me
16+
```
17+
18+
如果要进入主目录的某个子目录,通常会把子目录放在波浪号后面。
19+
20+
```bash
21+
# 进入 /home/me/foo 目录
22+
$ cd ~/foo
23+
```
24+
25+
如果`~`后面是已经存在的用户名,则会返回该用户的主目录。
26+
27+
```bash
28+
$ echo ~foo
29+
/home/foo
30+
31+
$ echo ~root
32+
/root
33+
```
34+
35+
上面例子中,Bash 会根据波浪号后面的用户名,返回该用户的主目录。
1036

11-
通配符早于正则表达式出现,可以看作是原始的正则表达式。它的功能没有正则那么强大灵活,但是胜在简单和方便。
37+
如果是不存在的用户名,则波浪号扩展不起作用。
38+
39+
```bash
40+
$ echo ~nonExistedUser
41+
~nonExistedUser
42+
```
43+
44+
此外,`~+`会返回当前所在的目录,等同于`pwd`命令。
45+
46+
```bash
47+
$ cd ~/foo
48+
$ echo ~+
49+
/home/me/foo
50+
```
1251

13-
## `?` 字符
52+
## `?` 字符扩展
1453

1554
`?`字符代表任意的单个字符,不包括空字符。比如,`Data???`匹配所有`Data`开头后面跟着三个字符的文件名。
1655

@@ -32,9 +71,21 @@ ab.txt
3271

3372
上面命令中,`??`匹配了两个字符。
3473

35-
注意,`?`不能匹配空字符。也就是说,它占据的位置必须有字符存在
74+
注意,Bash 是先进行扩展,再执行命令。因此,扩展的结果决定了命令执行的结果,各种扩展只是 Bash 的功能,命令本身并不存在参数扩展,收到什么参数就原样执行
3675

37-
## `*` 字符
76+
```bash
77+
# 当前目录有 a.txt 文件
78+
$ echo ?.txt
79+
a.txt
80+
81+
# 当前目录为空目录
82+
$ echo ?.txt
83+
?.txt
84+
```
85+
86+
上面例子中,如果`?.txt`可以扩展成文件名,`echo`命令会输出扩展后的结果;如果不能扩展成文件名,`echo`就会原样输出`?.txt`
87+
88+
## `*` 字符扩展
3889

3990
`*`字符代表任意数量的字符,包括零个字符。
4091

@@ -80,33 +131,44 @@ a.txt b.txt
80131

81132
上面命令中,`[ab]`表示可以扩展成`a``b`
82133

83-
方括号`[start-end]`表示一个连续的范围。
134+
方括号模式还有两种变体:`[^...]``[!...]`。它们表示匹配不在方括号里面的字符,这两种写法是等价的。比如,`[^abc]``[!abc]`表示匹配除了`a``b``c`以外的字符。
135+
136+
```bash
137+
$ ls ?[!a]?
138+
aba bbb
139+
```
140+
141+
上面命令中,`[!a]`表示文件名第二个字符不是`a`的文件名。
142+
143+
## [start-end] 模式
144+
145+
方括号模式`[start-end]`可以表示一个连续的范围。
84146

85147
```bash
86148
# 存在文件 a.txt、b.txt 和 c.txt
87149
$ ls [a-c].txt
88-
a.txt b.txt c.txt
150+
a.txt
151+
b.txt
152+
c.txt
89153

90154
# 存在文件 report1.txt、report2.txt 和 report3.txt
91155
$ ls report[0-9].txt
92-
report1.txt report2.txt report3.txt
156+
report1.txt
157+
report2.txt
158+
report3.txt
159+
...
93160
```
94161

95162
下面是更多的例子。
96163

164+
- `[a-z]`:所有小写字母。
165+
- `[a-zA-Z]`:所有小写字母与大写字母。
166+
- `[a-zA-Z0-9]`:所有小写字母、大写字母与数字。
97167
- `[abc]*`:所有以`a``b``c`字符之一开头的文件名。
168+
- `program.[co]`:文件`program.c`与文件`program.o`
98169
- `BACKUP.[0-9][0-9][0-9]`:所有以`BACKUP.`开头,后面是三个数字的文件名。
99170

100-
方括号模式还有两种变体:`[^...]``[!...]`。它们表示匹配不在方括号里面的字符,这两种写法是等价的。比如,`[^abc]``[!abc]`表示匹配除了`a``b``c`以外的字符。
101-
102-
```bash
103-
$ ls ?[!a]?
104-
aba bbb
105-
```
106-
107-
上面命令中,`[!a]`表示文件名第二个字符不是`a`的文件名。
108-
109-
这两种变体也可以使用连续范围的写法`[!start-end]`
171+
方括号模式的否定形式,也可以使用连续范围的写法`[!start-end]`,表示匹配不属于这个范围的字符。比如,`[!a-zA-Z]`表示匹配非英文字母的字符。
110172

111173
```bash
112174
$ echo report[!1–3].txt
@@ -117,7 +179,7 @@ report4.txt report5.txt
117179

118180
## 大括号扩展
119181

120-
大括号扩展`{...}`表示分别输出大括号里面的所有值。大括号内部,各个值之间使用逗号分隔。
182+
大括号扩展`{...}`表示分别输出大括号里面的所有值,各个值之间使用逗号分隔。这种扩展跟上面的扩展都不一样,不是文件名扩展,即不会扩展成文件名,而是扩展成所有给定的值
121183

122184
```bash
123185
$ echo {1,2,3}
@@ -273,49 +335,6 @@ $ mkdir {2007..2009}-{01..12}
273335

274336
上面命令会新建36个子目录,每个子目录的名字都是”年份-月份“。
275337

276-
## 波浪线扩展
277-
278-
波浪线`~`会自动扩展成当前用户的主目录。
279-
280-
```bash
281-
$ echo ~
282-
/home/me
283-
```
284-
285-
如果要进入主目录的某个子目录,通常会把子目录放在波浪号后面。
286-
287-
```bash
288-
# 进入 /home/me/foo 目录
289-
$ cd ~/foo
290-
```
291-
292-
如果`~`后面是已经存在的用户名,则会返回该用户的主目录。
293-
294-
```bash
295-
$ echo ~foo
296-
/home/foo
297-
298-
$ echo ~root
299-
/root
300-
```
301-
302-
上面例子中,Bash 会根据波浪号后面的用户名,返回该用户的主目录。
303-
304-
如果是不存在的用户名,则波浪号扩展不起作用。
305-
306-
```bash
307-
$ echo ~nonExistedUser
308-
~nonExistedUser
309-
```
310-
311-
此外,`~+`会返回当前所在的目录,等同于`pwd`命令。
312-
313-
```bash
314-
$ cd ~/foo
315-
$ echo ~+
316-
/home/me/foo
317-
```
318-
319338
## 变量扩展
320339

321340
Bash 将美元符号`$`开头的词元视为变量,将其扩展成变量值。

docs/grammar.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# Bash 的基本语法
22

3+
本章介绍 Bash 的最基本语法。
4+
35
## echo 命令
46

57
`echo`命令的作用是输出一行文本,可以将该命令的参数原样输出。
@@ -56,7 +58,7 @@ World
5658

5759
## 空格
5860

59-
Bash 使用空格区分不同的参数
61+
Bash 使用空格(或 Tab 键)区分不同的参数
6062

6163
```bash
6264
$ command foo bar
@@ -81,6 +83,10 @@ this is a test
8183
$ clear; ls
8284
```
8385

86+
上面例子中,Bash 先执行`clear`命令,执行完成后,再执行`ls`命令。
87+
88+
注意,使用分号时,第二个命令总是接着第一个命令执行,不管第一个命令执行成功或失败。
89+
8490
## 命令的分组和合并
8591

8692
Shell 允许将多个命令分组和合并执行。

docs/intro.md

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,20 @@ Shell 这个单词的原意是“外壳”,跟 kernel (内核)相对应,
1616

1717
Shell 有很多种,只要能给用户提供命令行环境的程序,都可以看作是 Shell。历史上,主要的 Shell 有 Bourne Shell(缩写为`sh`)、Bourne Again shell(缩写为`bash`)、C Shell(缩写为`csh`)、TENEX C Shell(缩写为`tcsh`)、Korn shell(缩写为`ksh`)、Z Shell(缩写为`zsh`)、Friendly Interactive Shell(缩写为`fish`)。Bash 是目前最常用的 Shell,除非特别指明,下文的 Shell 和 Bash 当作同义词使用,可以互换。
1818

19+
下面的命令可以查看当前运行的 Shell。
20+
21+
```bash
22+
$ echo $SHELL
23+
/bin/bash
24+
```
25+
1926
下面的命令可以查看当前的 Linux 系统安装的所有 Shell。
2027

2128
```bash
2229
$ cat /etc/shells
2330
```
2431

25-
上面命令中`$`是命令行环境的提示符,用户只需要输入提示符后面的内容`cat`命令可以显示文件内容,所以上面命令的意思,就是显示`/etc/shells`这个文件的内容,里面记录了当前文件安装的所有 Shell
32+
上面两个命令中`$`是命令行环境的提示符,用户只需要输入提示符后面的内容。
2633

2734
Linux 允许每个用户使用不同的 Shell,用户的默认 Shell 一般都是 Bash。
2835

@@ -44,14 +51,28 @@ Linux 允许每个用户使用不同的 Shell,用户的默认 Shell 一般都
4451

4552
注意,根用户(root)的提示符,不以美元符号(`$`)结尾,而以井号(`#`)结尾,用来提醒用户,现在具有根权限,可以执行各种操作,务必小心,不要出现误操作。
4653

47-
为了简洁,后文的命令行提示符都只使用`$`表示,用户只需输入这个符号后面的命令。你可以输入`pwd`命令,按下回车键,就会显示当前所在的目录。
54+
为了简洁,后文的命令行提示符都只使用`$`表示。
55+
56+
进入命令行环境以后,一般就已经打开 Bash 了。如果你的 Shell 不是 Bash,可以输入`bash`命令启动 Bash。
57+
58+
```bash
59+
$ bash
60+
```
61+
62+
退出 Bash 环境,可以使用`exit`命令,也可以同时`Ctrl + d`
63+
64+
```bash
65+
$ exit
66+
```
67+
68+
作为练习,可以试着输入`pwd`命令。按下回车键,就会显示当前所在的目录。
4869

4970
```bash
5071
$ pwd
51-
/home/user
72+
/home/me
5273
```
5374

54-
Shell 对用户相当友好。如果不小心输入了`pwe`,会返回一个提示,表示没有找到这个命令对应的可执行程序
75+
Shell 对用户相当友好。如果不小心输入了`pwe`,会返回一个提示,表示输入出错,没有对应的可执行程序
5576

5677
```bash
5778
$ pwe
@@ -131,7 +152,6 @@ Bash 单个命令一般都是一行,用户按下回车键,就开始执行。
131152
$ echo foo bar
132153

133154
# 等同于
134-
135155
$ echo foo \
136156
bar
137157
```

docs/quotation.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,19 @@ $ echo -e "a\tb"
4040
a b
4141
```
4242

43+
由于反斜杠可以对换行符转义,可以将一行命令写成多行。
44+
45+
```bash
46+
$ mv \
47+
/path/to/foo \
48+
/path/to/bar
49+
50+
# 等同于
51+
$ mv /path/to/foo /path/to/bar
52+
```
53+
54+
上面例子中,如果一条命令过长,就可以在行尾使用反斜杠,将其改写成多行。
55+
4356
## 单引号
4457

4558
单引号用于保留字符的字面含义,各种特殊字符都能在单引号里面变为普通字符,包括星号(`*`)、美元符号(`$`)、反斜杠(`\`)等。也就是说,单引号之中所有字符都会变成普通字符。

docs/script.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,16 @@ $ bash ./script.sh
4343
前面说过,通过 Shebang 行指定解释器的脚本,可以直接执行。这有一个前提条件,就是脚本需要有执行权限。可以使用下面的命令,赋予脚本执行权限。
4444

4545
```bash
46+
# 给所有用户执行权限
4647
$ chmod +x script.sh
48+
49+
# 给所有用户读权限和执行权限
50+
$ chmod +rx script.sh
51+
# 或者
52+
$ chmod 555 script.sh
53+
54+
# 只给脚本拥有者读权限和执行权限
55+
$ chmod u+rx script.sh
4756
```
4857

4958
除了执行权限,脚本调用时,一般需要指定脚本的路径。如果将脚本放在环境变量`$PATH`指定的目录中,就不需要指定路径了。因为 Bash 会自动到这些目录中,寻找是否存在同名的可执行文件。

docs/variable.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Bash 变量
22

3-
变量是指向某个内存区域的指针,通过变量名,可以读取该内存区域储存的信息。我们也可以把变量简单理解成一个变动的值
3+
变量是某个内存区域的标签,通过变量名,可以读取该内存区域储存的信息。你也可以把变量简单理解成一个变动的值
44

55
Shell 变量分成全局变量和局部变量两类。全局变量可以在所有 Shell 中访问,局部变量仅在当前 Shell 中可用。
66

0 commit comments

Comments
 (0)