学习阮一峰bash教程
提示
阮一峰的bash教程,地址在阮一峰Bash教程 (opens new window)
# 命令格式
bash
的命令格式总是这样的:command [arg1 ... [argN]]
- 参数有长短形式,
-l
等同于-list
# 命令组合符
&&
表示前一个命令执行成功后,才执行后一个命令||
表示前一个命令执行失败后,才执行后一个命令;
表示两个命令都执行,但并不关心执行结果
# 模式扩展
?
扩展,匹配任意一个字符,可以连用,例如??.txt
*
扩展,匹配任意多个字符.*
用来匹配隐藏文件,.[!.]*
用来匹配除了.
和..
之外的所有文件- Bash 4.0 引入了一个参数globstar,当该参数打开时,允许
**
匹配零个或多个子目录。因此,**/*
.txt可以匹配顶层的文本文件和任意深度子目录的文本文件。详细介绍请看后面shopt命令的介绍。
- 方括号扩展,匹配任意一个字符,同正则,可以使用范围,如
[a-z]
- 花括号扩展,扩展一个字符为给定的值,如
d{a,e,i,o,u}g
会变为dag
,deg
,dig
,dag
,dug
- ,前面可以没有值,表示空
- 花括号扩展可以与其他模式共用,且总是领先于其他模式
{a..b..c}
,会扩展为a-b,步长为c的序列- 多个扩展连用,会有类似循环的效果
echo {a..c}{1..3}
,输出a1 a2 a3 b1 b2 b3 c1 c2 c3
${!string*}
或${!string@}
返回所有匹配给定字符串string的变量名。$(...)
可以扩展成另一个命令的运行结果,该命令的所有输出都会作为返回值。
$ echo $(date)
Tue Jan 28 00:01:13 CST 2020
2
上面例子中,$(date)
返回 date
命令的运行结果。
还有另一种较老的语法,子命令放在反引号之中,也可以扩展成命令的运行结果。
$ echo `date`
Tue Jan 28 00:01:13 CST 2020
2
$(...)
可以嵌套,比如$(ls $(pwd))
。
$((...))
可以扩展成整数运算的结果。
$ echo $((2 + 2))
4
2
[[:class:]]
表示一个字符类,扩展成某一类特定字符之中的一个。常用的字符类如下。
[[:alnum:]]:匹配任意英文字母与数字
[[:alpha:]]:匹配任意英文字母
[[:blank:]]:空格和 Tab 键。
[[:cntrl:]]:ASCII 码 0-31 的不可打印字符。
[[:digit:]]:匹配任意数字 0-9。
[[:graph:]]:A-Z、a-z、0-9 和标点符号。
[[:lower:]]:匹配任意小写字母 a-z。
[[:print:]]:ASCII 码 32-127 的可打印字符。
[[:punct:]]:标点符号(除了 A-Z、a-z、0-9 的可打印字符)。
[[:space:]]:空格、Tab、LF(10)、VT(11)、FF(12)、CR(13)。
[[:upper:]]:匹配任意大写字母 A-Z。
[[:xdigit:]]:16进制字符(A-F、a-f、0-9)。
2
3
4
5
6
7
8
9
10
11
12
请看下面的例子。
$ echo [[:upper:]]*
上面命令输出所有大写字母开头的文件名。
字符类的第一个方括号后面,可以加上感叹号!(或^),表示否定。比如,![:digit:]匹配所有非数字。
$ echo [![:digit:]]*
上面命令输出所有不以数字开头的文件名。
字符类也属于文件名扩展,如果没有匹配的文件名,字符类就会原样输出。
不存在以大写字母开头的文件
$ echo [[:upper:]]*
[[:upper:]]*
2
上面例子中,由于没有可匹配的文件,字符类就原样输出了。
# 量词语法
量词语法用来控制模式匹配的次数。它只有在 Bash 的extglob参数打开的情况下才能使用,不过一般是默认打开的。下面的命令可以查询。
$ shopt extglob
extglob on
2
如果extglob参数是关闭的,可以用下面的命令打开。
$ shopt -s extglob
量词语法有下面几个。
?(pattern-list):模式匹配零次或一次。
*(pattern-list):模式匹配零次或多次。
+(pattern-list):模式匹配一次或多次。
@(pattern-list):只匹配一次模式。
!(pattern-list):匹配给定模式以外的任何内容。
2
3
4
5
$ ls abc?(.)txt
abctxt abc.txt
2
上面例子中,?(.)匹配零个或一个点。
$ ls abc?(def)
abc abcdef
2
上面例子中,?(def)匹配零个或一个def。
$ ls abc@(.txt|.php)
abc.php abc.txt
2
上面例子中,@(.txt|.php)匹配文件有且只有一个.txt或.php后缀名。
$ ls abc+(.txt)
abc.txt abc.txt.txt
2
上面例子中,+(.txt)匹配文件有一个或多个.txt后缀名。
$ ls a!(b).txt
a.txt abb.txt ac.txt
2
上面例子中,!(b)表示匹配单个字母b以外的任意内容,所以除了ab.txt以外,其他文件名都能匹配。
量词语法也属于文件名扩展,如果不存在可匹配的文件,就会原样输出。
没有 abc 开头的文件名
$ ls abc?(def)
ls: 无法访问'abc?(def)': 没有那个文件或目录
2
上面例子中,由于没有可匹配的文件,abc?(def)就原样输出,导致ls命令报错。
# shopt
命令
shopt命令可以调整 Bash 的行为。它有好几个参数跟通配符扩展有关。
shopt命令的使用方法如下。
打开某个参数
$ shopt -s [optionname]
关闭某个参数
$ shopt -u [optionname]
查询某个参数关闭还是打开
$ shopt [optionname]
- dotglob 参数
dotglob参数可以让扩展结果包括隐藏文件(即点开头的文件)。
正常情况下,扩展结果不包括隐藏文件。
$ ls *
abc.txt
2
打开dotglob,就会包括隐藏文件。
$ shopt -s dotglob
$ ls *
abc.txt .config
2
3
- nullglob 参数
nullglob参数可以让通配符不匹配任何文件名时,返回空字符。
默认情况下,通配符不匹配任何文件名时,会保持不变。
$ rm b*
rm: 无法删除'b*': 没有那个文件或目录
2
上面例子中,由于当前目录不包括b开头的文件名,导致b*不会发生文件名扩展,保持原样不变,所以rm命令报错没有b*这个文件。
打开nullglob参数,就可以让不匹配的通配符返回空字符串。
$ shopt -s nullglob
$ rm b*
rm: 缺少操作数
2
3
上面例子中,由于没有b*匹配的文件名,所以rm b*扩展成了rm,导致报错变成了”缺少操作数“。
- failglob 参数
failglob参数使得通配符不匹配任何文件名时,Bash 会直接报错,而不是让各个命令去处理。
$ shopt -s failglob
$ rm b*
bash: 无匹配: b*
2
3
上面例子中,打开failglob以后,由于b*不匹配任何文件名,Bash 直接报错了,不再让rm命令去处理。
- extglob 参数
extglob参数使得 Bash 支持 ksh 的一些扩展语法。它默认应该是打开的。
$ shopt extglob
extglob on
2
它的主要应用是支持量词语法。如果不希望支持量词语法,可以用下面的命令关闭。
$ shopt -u extglob
- nocaseglob 参数
nocaseglob参数可以让通配符扩展不区分大小写。
$ shopt -s nocaseglob
$ ls /windows/program*
/windows/ProgramData
/windows/Program Files
/windows/Program Files (x86)
2
3
4
5
上面例子中,打开nocaseglob以后,program*就不区分大小写了,可以匹配ProgramData等。
- globstar 参数
globstar参数可以使得**匹配零个或多个子目录。该参数默认是关闭的。
假设有下面的文件结构。
a.txt sub1/b.txt sub1/sub2/c.txt 上面的文件结构中,顶层目录、第一级子目录sub1、第二级子目录sub1\sub2里面各有一个文本文件。请问怎样才能使用通配符,将它们显示出来?
默认情况下,只能写成下面这样。
$ ls *.txt */*.txt */*/*.txt
a.txt sub1/b.txt sub1/sub2/c.txt
2
这是因为*只匹配当前目录,如果要匹配子目录,只能一层层写出来。
打开globstar参数以后,匹配零个或多个子目录。因此,/*.txt就可以得到想要的结果。
$ shopt -s globstar
$ ls **/*.txt
a.txt sub1/b.txt sub1/sub2/c.txt
2
3
提示
在阅读过程中发现,bash的教程对我并没有太大的工作上的帮助,剩余的内容我将阅读,不做整理,必要时查阅教程。