分类: LINUX
2009-07-11 18:11:29
计算命令行时,shell会用元字符来缩写能够匹配某个特定字符组的文件名或路径名。表13-11中所列的文件名替换元字符将被展开为一组按字母顺序排列的文件名。将元字符展开为文件名的过程又被称作文件名替换或globbing。如果没有文件名能够跟所用的元字符匹配,shell就会把这个元字符作为一个字面字符。
表13-11 shell元字符与文件名替换
元 字 符 |
含 义 |
* |
匹配零个或多个字符 |
? |
匹配一个字符 |
[abc] |
匹配a、b、c这组字符中的一个 |
[!abc] |
匹配a、b、c这组字符以外的某个字符 |
{a,ile,ax} |
匹配一个或一组字符 |
[a–z] |
匹配在a至z这个范围内的某个字符 |
[!a~z] |
匹配不在a至z这个范围内的某个字符 |
\ |
转义或禁用后面那个元字符 |
星号是一个通配符,它匹配文件名中零个或多个任意字符。
范例13-41
1 $ ls *
abc abc1 abc122 abc123 abc2 file1 file1.bak file2 file2.bak none
nonsense nobody nothing nowhere one
2 $ ls *.bak
file1.bak file2.bak
3 $ echo a*
ab abc1 abc122 abc123 abc2
说明
1. 星号被展开为当前工作目录下的所有文件的名称。所有的文件名都作为参数传给ls并在显示出来。
2. 匹配并列出所有以零个或多个字符开头、.bak结尾的文件名。
3. 匹配所有以a开头、后跟零个或多个字符的文件名,并将它们作为参数传给echo命令。
问号代表文件名中某一单个字符。当文件名中包含一个或多个问号时,shell把问号替换为在文件名中匹配到的字符,以这种方式来完成文件名替换。
范例13-42
1 $ ls
abc abc122 abc2 file1.bak file2.bak nonsense nothing one
abc1 abc123 file1 file2 none noone nowhere
2 $ ls a?c?
abc1 abc2
3 $ ls ??
ls: ??: No such file or directory
4 $ echo abc???
abc122 abc123
5 $ echo ??
??
说明
1. 列出当前目录下的文件。
2. 匹配并列出以a开头,后跟一个字符,再跟字符c和一个字符的文件名。
3. 如果找到正好由两个字符组成的文件名,就列出来。因为当前目录下没有名字为两个字符的文件,所以这两个问号被解释为由两个字面字符“?”组成的文件名。如果没有找到这样的文件,就打印出一条错误信息。
4. 扩展以abc开头、后跟正好3个字符的文件名,并用echo命令显示。
5. 当前目录下没有名字正好是两个字符的文件。shell找不到匹配,就把问号当成一个字面上的问号。
括号用于匹配包含指定字符组或字符范围内某个字符的文件名。
范例13-43
1 $ ls
abc abc122 abc2 file1.bak file2.bak nonsense nothing
one abc1 abc123 file1 file2 none noone nowhere
2 $ ls abc[123]
abc1 abc2
3 $ ls abc[1–3]
abc1 abc2
4 $ ls [a–z][a–z][a–z]
abc one
5 $ ls [!f–z]???
abc1 abc2
6 $ ls abc12[23]
abc122 abc123
说明
1. 列出当前目录下所有文件。
2. 匹配所有包含4个字符的文件名,列出以abc开头,后跟1、2或3的文件名。只匹配方括号中这组字符中的任一个。
3. 匹配所有包含4个字符的文件名,列出以abc开头,后跟一个1~3之间数字的文件名。
4. 匹配所有包含3个字符的文件名,列出由3个小写字母组成的文件名。
5. 列出所有包含4个字符、第1个字符不是f至z之间的小写字母([!f-z]),后面是3个任意字符的文件名,这里?代表一个字符。
6. 列出文件名以abc12开头,后跟2或3的文件。
花括号用来匹配一组用逗号分隔的字符串中的任一个。左花括号之前的所有字符称为前文(preamble),右花括号之后的所有字符称为后文(preamble)。前文和后文都是可选的。花括号中不能包含不加引号的空白符。
范例13-44
1 $ ls
a.c b.c abc ab3 ab4 ab5 file1 file2 file3 file4 file5 foo
faa fumble
2 $ ls f{oo,aa,umble}
foo faa fumble
3 $ ls a{.c,c,b[3-5]}
a.c ab3 ab4 ab5
4 $ mkdir /usr/local/src/bash/{old,new,dist,bugs}
5 $ chown root /usr/{ucb/{ex,edit},lib/{ex?.?*,how_ex}}
6 $ echo fo{o, um}*
fo{o, um}*
7 $ echo {mam,pap,ba}a
mama papa baa
8 $ echo post{script,office,ure}
postscript postoffice posture
说明
1. 列出当前目录下的所有文件。
2. 匹配文件名以f开头,后跟括号中任一字符串(oo、aa或umble)的文件。若在括号中加入了空格符,则会出现错误信息“Missing}”。
3. 匹配文件名以a开头,后跟括号中任一字符串(.c、c、b3、b4或b5)的文件。花括号中允许使用方括号。
4. 在/usr/local/src/bash目录下创建4个新目录,它们分别为:old,new,dist和bugs。
5. root用户权限将指派给/usr/ucb目录下的ex和edit文件,以及/usr/lib目录下的文件名以ex开头,后跟1个字符,1个句点,1个或多个任意字符的文件和名为how_ex的文件。
6. 只要括号中出现未加引号的空格就不对括号进行扩展。
7. 括号扩展不见得总是扩展文件名。本例中,括号后的字符a被添加到括号中的每个字符串后面并在结果中显示。
8. 前缀是一个字符串post,后跟由括号括着的以逗号分隔的字符串。括号扩展已被执行并在结果中显示。
反斜杠用于屏蔽某一单个字符的特殊含义。被转义的字符将只代表其本身。
范例13-45
1 $ ls
abc file1 youx
2 $ echo How are you?
How are youx
3 $ echo How are you\?
How are you?
4 $ echo When does this line \
> ever end\?
When does this line ever end?
说明
1. 列出当前目录下的所有文件(注意youx文件)。
2. shell对?执行文件名扩展。匹配当前目录下所有以you开头,后面有且只有一个字符的文件名,把它们替换到字符串中。文件名youx将被替换到字符串中,把字符串变成:How are youx (这好像不是我们想要的结果)。
3. 在问号前面加一个反斜杠,问号就被转义了,这意味着shell不会再把它当作通配符来解释。
4. 在换行符前面加一个反斜杠将其转义。次提示符将一直出现直到字符串被换行符终止。转义问号(?),不对它执行文件名替换。
代字符号被bash shell(来自C shell)用来作路径扩展。代字符号指代的是用户的主目录的完全路径名 。当给代字符号添加一个用户名时,它扩展成该用户的全路径名。
当在代字符号后跟一个加号时,PWD(当前工作目录)的值将替换代字符号。当代字符号后跟一个连字号时,将被上一个工作目录替换。OLDPWD也是指上一个工作目录。
范例13-46
1 $ echo ~
/home/jody/ellie
2 $ echo ~joe
/home/joe
3 $ echo ~+
/home/jody/ellie/perl
4 $ echo ~–
/home/jody/ellie/prac
5 $ echo $OLDPWD
/home/jody/ellie/prac
6 $ cd –
/home/jody/ellie/prac
说明
1. 代字符号的值为用户的主目录的完全路径名。
2. 在用户名前的代字符号的值为joe的主目录的完全路径名。
3. ~+符号的值为工作目录的完全路径名。
4. ~-符号的值为上一个工作目录。
5. OLDPWD变量包含上一个工作目录。
6. 连字符代表上一个工作目录。cd命令回到上一个工作目录并显示该目录。
一旦设置了bash变量noglob,或给set命令带了-f选项,文件名替换(也称为globbing)功能就被关闭,这意味着所有的元字符都将只代表其自身,它们不再被用作通配符。使用grep、sed或awk之类的程序搜索模式时,要用到关闭元字符的功能,因为shell可能会试图去展开这些程序使用的元字符。如果没有设置globbing,所有的元字符必须用一个反斜杠来转义以关闭通配符解释。
内置的shopt命令(bash 2.x版本)也支持控制globbing的选项。
范例13-47
1 $ set noglob or set -f
2 $ print * ?? [] ~ $LOGNAME
* ?? [] /home/jody/ellie ellie
3 $ unset noglob or set +f
4 $ shopt -s dotglob # Only available in bash versions 2.x
5 $ echo *bash*
.bash_history .bash_logout .bash_profile .bashrc bashnote
bashtest
说明
1. –f选项作为set命令的参数。它关闭通配符用于文件名扩展的特殊含义。
2. 文件名扩展元字符被显示为其自身,没有经过任何解释。注意代字符号和美元符仍然被扩展了,因为它们没有用于文件名扩展。
3. 如果没有设置noglob或设置了+f选项,文件名元字符会被扩展。
4. shopt内置命令可以为shell设置选项。dotglob选项允许文件名用globbing元字符匹配,甚至是以一个点开头的文件名。通常以点开头的文件是不可见的,并且在执行文件名扩展时不会被识别。
5. 因为在第4行设置了dotglob选项,所以当通配符*用于文件名扩展时,如果以点开头的文件名包含模式bash,它也会被扩展。
bash 2.x还包含这种来自Korn shell的模式匹配功能,允许正则表达式类型的语法(参见表13-12)。除非shopt命令的extglob选项被打开:
shopt –s extglob
否则正则表达式操作符不会被识别。
表13-12 扩展的模式匹配
正则表达式 |
含 义 |
abc?(2|9)1 |
?与零个或一个出现的括号中的任意模式相匹配。竖杠代表一个或条件。例如,2或9。匹配abc21、abc91或者 abc1 |
abc*([0-9]) |
*与零个或多个出现的括号中的任意模式相匹配。匹配abc后跟零个或多个数字。如,abc、abc1234、abc3、abc2等 |
abc+([0-9]) |
+与一个或多个出现的括号中的任意模式相匹配。匹配abc后跟一个或多个数字。例如,abc3、abc123等 |
no@(one|ne) |
@正好与括号中任一模式相匹配。匹配noone或none |
no!(thing|where) |
!与括弧中的任意模式除外的其他所有串相匹配。匹配no、nobody或noone,但不能是nothing或nowhere |
范例13-48
1 $ shopt -s extglob
2 $ ls
abc abc122 f1 f3 nonsense nothing one
abc1 abc2 f2 none noone nowhere
3 $ ls abc?(1|2)
abc abc1 abc2
4 $ ls abc*([1-5])
abc abc1 abc122 abc2
5 $ ls abc+([0-5])
abc1 abc122 abc2
6 $ ls no@(thing|ne)
none nothing
7 $ ls no!(thing)
none nonsense noone nowhere
说明
1. shopt内置命令用来设置extglob(扩展globbing)选项,允许bash识别扩展的模式匹配字符。
2. 列出当前工作目录下的所有文件。
3. 匹配以abc开头后跟零个或一个括弧中的任意模式的文件名。匹配abc、abc1或abc2。
4. 匹配以abc开头后跟零个或多个1~5之间的数字的文件名。匹配abc、abc1、abc122、abc123和abc2。
5. 匹配以abc开头后跟一个或多个0~5之间的数字的文件名。匹配abc1、abc122、abc123和abc2。
6. 匹配以no开头后跟指定串thing或ne的文件名。匹配nothing或none。
7. 匹配以no开头后跟除thing外的字符串的文件名。匹配none、nonsense、noone和nowhere。!意思是非。