正则表达式之道原著:Steve Mansour 翻译:Neo Lee 译者按:原文因为年代久远,文中很多链接早已过期(主要是关于vi、sed等工具的介绍和手册),本译文中已将此类链接删除,如需检查这些链接可以 查看上面链接的原文。除此之外基本照原文直译,括号中有“译者按”的部分是译者补充的说明。如有内容方面的问题请直接和Steve Mansor联系,当然,如果你只写中文,也可以和我联系。 目 录什么是正则表达式
什么是正则表达式一个正则表达式,就是用某种模式去匹配一类字符串的一个公式。很多人因为它们看上去比较古怪而且复杂所以不敢去使用——很不幸,这篇文章也不能够改变这一 点,不过,经过一点点练习之后我就开始觉得这些复杂的表达式其实写起来还是相当简单的,而且,一旦你弄懂它们,你就能把数小时辛苦而且易错的文本处理工作 压缩在几分钟(甚至几秒钟)内完成。正则表达式被各种文本编辑软件、类库(例如Rogue Wave的tools.h++)、脚本工具(像awk/grep/sed)广泛的支持,而且像Microsoft的Visual C++这种交互式IDE也开始支持它了。我们将在如下的章节中利用一些例子来解释正则表达式的用法,绝大部分的例子是基于vi中的文本替换命令和grep文件搜索命令来书写的,不过它们都是比较典型的例子,其中的概念可以在sed、awk、perl和其他支持正则表达式的编程语言中使用。你可以看看不同工具中的正则表达式这一节,其中有一些在别的工具中使用正则表达式的例子。还有一个关于vi中文本替换命令(s)的简单说明附在文后供参考。 正则表达式基础正则表达式由一些普通字符和一些元字符(metacharacters)组成。普通字符包括大小写的字母和数字,而元字符则具有特殊的含义,我们下面会给予解释。在最简单的情况下,一个正则表达式看上去就是一个普通的查找串。例如,正则表达式"testing"中没有包含任何元字符,,它可以匹配"testing"和"123testing"等字符串,但是不能匹配"Testing"。 要想真正的用好正则表达式,正确的理解元字符是最重要的事情。下表列出了所有的元字符和对它们的一个简短的描述。
最简单的元字符是点,它能够匹配任何单个字符(注意不包括新行符)。假定有个文件test.txt包含以下几行内容:
he is in a rut the food is Rotten I like root beer
要想匹配行首的字符要使用抑扬字符(^)——又是也被叫做插入符。例如,想找到text.txt中行首"he"打头的行,你可能会先用简单表达式he,但是这会匹配第三行的the,所以要使用正则表达式^he,它只匹配在行首出现的h。 有时候指定“除了×××都匹配”会比较容易达到目的,当抑扬字符(^)出现在方括号中是,它表示“排除”,例如要匹配he ,但是排除前面是t or s的情性(也就是the和she),可以使用:[^st]he。 可以使用方括号来指定多个字符区间。例如正则表达式[A-Za-z]匹配任何字母,包括大写和小写的;正则表达式[A-Za-z][A-Za-z]* 匹配一个字母后面接着0或者多个字母(大写或者小写)。当然我们也可以用元字符+做到同样的事情,也就是:[A-Za-z]+ ,和[A-Za-z][A-Za-z]*完全等价。但是要注意元字符+ 并不是所有支持正则表达式的程序都支持的。关于这一点可以参考后面的正则表达式语法支持情况。 要指定特定数量的匹配,要使用大括号(注意必须使用反斜杠来转义)。想匹配所有100和1000的实例而排除10和10000,可以使用:10\{2,3\},这个正则表达式匹配数字1后面跟着2或者3个0的模式。在这个元字符的使用中一个有用的变化是忽略第二个数字,例如正则表达式0\{3,\} 将匹配至少3个连续的0。 简单的例子这里有一些有代表性的、比较简单的例子。
中级的例子(神奇的咒语)例1将所有方法foo(a,b,c)的实例改为foo(b,a,c)。这里a、b和c可以是任何提供给方法foo()的参数。也就是说我们要实现这样的转换:
下面这条替换命令能够实现这一魔法:
现在让我们把它打散来加以分析。写出这个表达式的基本思路是找出foo()和它的括号中的三个参数的位置。第一个参数是用这个表达式来识别的::\([^,]*\),我们可以从里向外来分析它:
现在正是指出一个使用正则表达式常见错误的最佳时机。为什么我们要使用[^,]*这样的一个表达式,而不是更加简单直接的写法,例如:.*,来匹配第一个参数呢?设想我们使用模式.*来匹配字符串"10,7,2",它应该匹配"10,"还是"10,7,"?为了解决这个两义性(ambiguity),正则表达式规定一律按照最长的串来,在上面的例子中就是"10,7,",显然这样就找出了两个参数而不是我们期望的一个。所以,我们要使用[^,]*来强制取出第一个逗号之前的部分。 这个表达式我们已经分析到了:foo(\([^,]*\),这一段可以简单的翻译为“当你找到foo(就把其后直到第一个逗号之前的部分标记为\1”。然后我们使用同样的办法标记第二个参数为\2。 对第三个参数的标记方法也是一样,只是我们要搜索所有的字符直到右括号。我们并没有必要去搜索第三个参数,因为我们不需要调整它的位置,但是这样的模式能 够保证我们只去替换那些有三个参数的foo()方法调用,在foo()是一个重载(overoading)方法时这种明确的模式往往是比较保险的。然后, 在替换部分,我们找到foo()的对应实例,然后利用标记好的部分进行替换,是的第一和第二个参数交换位置。 例2假设有一个CSV(comma separated value)文件,里面有一些我们需要的信息,但是格式却有问题,目前数据的列顺序是:姓名,公司名,州名缩写,邮政编码,现在我们希望讲这些数据重新组 织,以便在我们的某个软件中使用,需要的格式为:姓名,州名缩写-邮政编码,公司名。也就是说,我们要调整列顺序,还要合并两个列来构成一个新列。另外, 我们的软件不能接受逗号前后面有任何空格(包括空格和制表符)所以我们还必须要去掉逗号前后的所有空格。这里有几行我们现在的数据:
Sharon Lee Smith, Design Works Incorporated, CA, 95012 B. Amos , Hill Street Cafe, CA, 95013 Alexander Weatherworth, The Crafts Store, CA, 95014 ...
Sharon Lee Smith,CA 95012,Design Works Incorporated B. Amos,CA 95013,Hill Street Cafe Alexander Weatherworth,CA 95014,The Crafts Store ... 下面就是第一个替换命令:
下面这个替换命令则用来去除空格:
例3假设有一个多字符的片断重复出现,例如:Billy tried really hard而你想把"really"、"really really",以及任意数量连续出现的"really"字符串换成一个简单的"very"(simple is good!),那么以下命令: :%s/\(really \)\(really \)*/very /就会把上述的文本变成: Billy tried very hard表达式\(really \)*匹配0或多个连续的"really "(注意结尾有个空格),而\(really \)\(really \)* 匹配1个或多个连续的"really "实例。 困难的例子(不可思议的象形文字)Coming soon.
不同工具中的正则表达式OK,你已经准备使用RE(regular expressions,正则表达式),但是你并准备使用vi。所以,在这里我们给出一些在其他工具中使用RE的例子。另外,我还会总结一下你在不同程序之间使用RE可能发现的区别。当然,你也可以在Visual C++编辑器中使用RE。选择Edit->Replace,然后选择"Regular expression"选择框,Find What输入框对应上面介绍的vi命令:%s/pat1/pat2/g中的pat1部分,而Replace输入框对应pat2部分。但是,为了得到vi的执行范围和g选项,你要使用Replace All或者适当的手工Find Next and Replace(译者按:知道为啥有人骂微软弱智了吧,虽然VC中可以选中一个范围的文本,然后在其中执行替换,但是总之不够vi那么灵活和典雅)。 sedSed是Stream EDitor的缩写,是Unix下常用的基于文件和管道的编辑工具,可以在手册中得到关于sed的详细信息。 这里是一些有趣的sed脚本,假定我们正在处理一个叫做price.txt的文件。注意这些编辑并不会改变源文件,sed只是处理源文件的每一行并把结果显示在标准输出中(当然很容易使用重定向来定制):
awkawk是一种编程语言,可以用来对文本数据进行复杂的分析和处理。可以在手册中得到关于awk的详细信息。这个古怪的名字是它作者们的姓的缩写(Aho,Weinberger和Kernighan)。在Aho,Weinberger和Kernighan的书The AWK Programming Language中有很多很好的awk的例子,请不要让下面这些微不足道的脚本例子限制你对awk强大能力的理解。我们同样假定我们针对price.txt文件进行处理,跟sed一样,awk也只是把结果显示在终端上。
grepgrep是一个用来在一个或者多个文件或者输入流中使用RE进行查找的程序。它的name编程语言可以用来针对文件和管道进行处理。可以在手册中得到关于grep的完整信息。这个同样古怪的名字来源于vi的一个命令,g/re/p,意思是global regular expression print。下面的例子中我们假定在文件phone.txt中包含以下的文本,——其格式是姓加一个逗号,然后是名,然后是一个制表符,然后是电话号码: Francis, John 5-3871
egrepegrep是grep的一个扩展版本,它在它的正则表达式中支持更多的元字符。下面的例子中我们假定在文件phone.txt中包含以下的文本,——其格式是姓加一个逗号,然后是名,然后是一个制表符,然后是电话号码:
Wong, Fred 4-4123 Jones, Thomas 1-4122 Salazar, Richard 5-2522
|
| 命令或环境 | . | [ ] | ^ | $ | \( \) | \{ \} | ? | + | | | ( ) |
| vi | X | X | X | X | X | |||||
| Visual C++ | X | X | X | X | X | |||||
| awk | X | X | X | X | X | X | X | X | ||
| sed | X | X | X | X | X | X | ||||
| Tcl | X | X | X | X | X | X | X | X | X | |
| ex | X | X | X | X | X | X | ||||
| grep | X | X | X | X | X | X | ||||
| egrep | X | X | X | X | X | X | X | X | X | |
| fgrep | X | X | X | X | X | |||||
| perl | X | X | X | X | X | X | X | X | X |
s 表示其后是一个替换命令。
pat1 这是要查找的一个正则表达式,这篇文章中有一大堆例子。
g 可选标志,带这个标志表示替换将针对行中每个匹配的串进行,否则则只替换行中第一个匹配串。
2007 年 5 月 28 日
几乎所有重要问题都需要从无用数据中过滤出有用数据。了解大量的 UNIX® 命令行实用工具如何使用正则表达式 来去芜取精。
非常奇怪,直到今天我仍然能重复周六早上的经典歌曲“Conjunction Junction”。这是好事(看了太多电视)还是坏事(也许是我现在职业的先兆)仍然有待讨论。不管怎样,这首小调在欢快的节奏下传递了基本的信息。
我还没有为学习 UNIX 构想出与“Conjunction Junction”相似的作品,但是我会在未来的几个月里尝试亲手编写这样的歌曲。与此同时,趁着快乐回忆所带来的好心情,我们继续以 Schoolhouse 摇滚的传统学习方式攻克命令行。
现在开始上课。吐出嘴里的口香糖,回到您的座位上,然后拿出一根二号铅笔。还有您,Spicoli。
您可以将 UNIX 命令行看作是一句话:
|(管道)或 >(重定向标准输出),是连词——用于连接句子。例如,命令行:ls -A | wc -l 用于计算当前目录下的条目数(忽略特殊条目 . 和 ..),它包含两个句子。第一个句子 ls -A 是动词结构,列举当前目录下的内容,第二个句子 wc -l 是另一个动词结构,用于计算行数。第一个句子输出的结果作为第二个句子的输入,并由连接词(管道)连接这两个句子。
在本系列文章以及其他文章中展示的许多您可能已经学习过的命令行句式都具有这种句子结构。
但是,如果缺少了文法上的修饰语,命令行将显得不专业。当然,基本句子也能完成工作,但是这样显得不优美。(在此对高中英语演唱二人组 Rad 女士和 Perlstein 女士表示歉意。)解决更有趣的问题需要用到形容词。
几乎所有重要问题都需要从无用数据中过滤出有用数据。虽然属性的数量和种类会有所不同,但是每种方案都通过某种方式(形式或格式),隐式或显式地描述了它要查找并处理的信息,从而生成另外一种形式的其他信息。
在命令行中,正则表达式 的作用相当于形容词——一种描述或限定词。在应用到输出时,正则表达式可辨别相关数据和无关数据。
让我们看一个示例问题。
grep 实用工具逐行过滤输入并寻找匹配。grep 的最简单应用是打印那些包含与某个模式匹配的文本的行。grep 可以查找具有固定顺序的字符组合,甚至可以通过使用 -i 选项来忽略大小写。
因此,假定文件 heroes.txt 包含以下行:
Catwoman |
命令行:
grep -i man heroes.txt |
将生成:
Catwoman |
其中 grep 扫描 heroes.txt 文件中的每一行并查找字母 m,后面紧跟 a,然后紧跟 n。除了必须保证相邻,这些字母可以出现在行的任何位置,甚至可以位于较大的单词中间。在不考虑大小写的情况下(-i 选项),Catwoman、Batman、Spider Man、Wonder Woman、Ant Man、Aquaman 和 Martian Manhunter 都包含字符串 man。
grep 实用工具包含其他可优化搜索的内置选项。例如,-w 选项限制于匹配整个单词,因此 grep -i -w man 将排除 Catwoman 和 Batman(举例来说)。
该工具还有一个优秀的功能,可以排除而不是包括所有匹配的搜索结果。使用 -v 选项来排除 匹配的行。例如:
grep -v -i 'spider' heroes.txt |
将打印除了包含字符串 spider 之外的所有行。
Catwoman |
但是,对于以下这些情况,您该如何处理?只希望得到那些开头为“Bat”的单词;或者以“bat”、“Bat”、“cat”或“Cat”开头的单词?或者希望知道有多少漫画复仇者的名字以“man”结束。在这些实例中,类似于上述三个示例的简单字符串搜索将无法满足要求,因为这些搜索不区分位置。
正则表达式可以 过滤特定的位置,例如行的开始或结束,以及单词的开始和结束。正则表达式(通常简写为 regex)还可以描述:备选项(您可将其称为“this”或“that”);固定长度、可变长度或不定长度的重复;范围(例如,“a-m 之间的任意字母”);还有字符的类别或种类(“可打印字符”或“标点符号”),以及其他技术。
表 1 显示了一些常用的正则表达式操作符。您可以连接表 1 中显示的元素(以及其他操作符)并加以组合使用,从而构建(非常)复杂的正则表达式。
| 操作符 | 用途 |
|---|---|
.(句号) | 匹配任意单个字符。 |
^(脱字号) | 匹配出现在行首或字符串开始位置的空字符串。 |
$(美元符号) | 匹配出现在行末的空字符串。 |
A
| 匹配大写字母 A。 |
a
| 匹配小写字母 a。 |
\d
| 匹配任意一位数字。 |
\D
| 匹配任意单个非数字字符。 |
\w
| 匹配任意单个字母数字字符,同义词是 [:alnum:]。 |
[A-E]
| 匹配任意大写的 A、B、C、D 或 E。 |
[^A-E]
| 匹配除 A、B、C、D 和 E 之外的任意字符。 |
X?
| 匹配出现零次或一次的大写字母 X。 |
X*
| 匹配零个或任意个大写 X。 |
X+
| 匹配一个或多个字母 X。 |
X{n}
| 精确匹配 n 个字母 X。 |
X{n,m}
| 匹配最少 n 个并且不超过 m 个字母 X。如果省略 m,表达式将尝试匹配最少 n 个 X。 |
(abc|def)+
| 匹配一连串的(最少一个) abc 或 def;abc 和 def 将匹配。 |
以下是一些使用 grep 作为搜索工具的正则表达式示例。许多其他 UNIX 工具,包括交互式编辑器 vi 和 Emacs、流编辑器 sed 和 awk,以及所有现代编程语言都支持正则表达式。在您学会正则表达式的语法(也许相当晦涩)之后,就可以将您的专业知识灵活运用到不同的工具、编程语言和操作系统。
要查找以“Bat”开头的名称,请使用:
grep -E '^Bat' |
可以使用 -E 选项来指定正则表达式。^(脱字号)字符匹配行首或字符串的开头,这是一个出现在每行或每个字符串开头字符之前的假想字符。字母 B、a 和 t 只具有字面含义并且仅匹配那些特定的字符。因此,命令 grep -E '^Bat' 将生成:
Batman |
由于许多 regex 操作符也为 Shell 所使用(其中一些具有不同的用途,另外一些则有类似的用途),因此一个好的习惯是使用单引号将命令行中的每个 regex 括起来,以保护 regex 操作符免遭 Shell 的误解。例如,*(星号)和 $(美元符号)都是 regex 操作符,并且对于您的 Shell 具有特殊的含义。
要查找以“man”结尾的名称,可以使用 regex man$ 来匹配序列 m、a 和 n,并且后面紧接与 regex 操作符 $ 匹配的行(字符串)。
基于 ^ 和 $ 的作用,您可以使用 regex ^$ 来查找空行(相当于在开始之后立即结束的行)。
要查找以“bat”、“Bat”、“cat”或“Cat”开头的单词,可以使用以下两个技巧。首先是备选项,如果备选项中的任意 模式匹配,都会产生匹配的结果。例如,命令:
grep -E '^(bat|Bat|cat|Cat)' heroes.txt |
可实现这一技巧。regex 操作符 |(竖线)表示备选项,因此 this|that 匹配字符串 this 或字符串 that。因此,^(bat|Bat|cat|Cat) 表示“行首紧跟 bat、Bat、cat 或 Cat之一。”当然,可以使用 grep -i 来简化该 regex,这样可以忽略大小写,从而将命令简化为:
grep -i -E '^(bat|cat)' heroes.txt |
匹配“bat”、“Bat”、“cat”或“Cat”的另一个方法是使用 [ ](方括号)集合 操作符。如果将一组字符放在一个集合中,则可以匹配那些字符中的任意一个。(您可以将集合 看作是字符备选项的简写法。)
例如,命令行:
grep -E '^[bcBC]at' heroes.txt |
与以下命令生成的结果相同:
grep -E '^(bat|Bat|cat|Cat)' heroes.txt |
您可以再次使用 -i 将 regex 简化为 ^[bc]at。
而且,还可以使用 -(连字符)操作符在集合中指定包含的字符范围。例如,用户名通常以字母开头。假定要在提交给您的服务器的 Web 表格中验证这样的用户名,可以使用类似于 ^[A-Za-z] 的 regex。此 regex 表示“字符串的开头后紧跟任意大写字母 (A-Z) 或任意小写字母 (a-z)。”顺便说明一下,[A-z] 与 [A-Za-z] 作用相同。
还可以在集合中混合使用范围和单个字符。regex [A-MXYZ] 将匹配任意大写的 A-M、X、Y 和 Z。
并且,如果希望反转集合(即排除集合中的任意字符),可以使用特殊集合 [^ ] 并包含要排除的范围或字符。以下是反转集合的示例。要查找所有名称中包含 at 的超级英雄,并排除 Dark Knight 和 Batman,请键入:
grep -i -E '[^b]at' heroes.txt |
此命令生成:
Catwoman |
由于某些集合需要经常使用,所以设计出简化符号以代替大量字符。例如,集合 [A-z0-9_] 十分常用,因此可以简写为 \w。与此类似,操作符 \W 是集合 [^A-z0-9_] 的简写。还可以使用符号 [:alnum:] 代替 \w,使用 [^[:alnum:]] 代替 \W。
顺便说明一下,\w(以及同义词 [:alnum:])是特定于区域的,而 [A-z0-9_] 即表示字母 A-z、数字 0-9 和下划线。如果要开发国际化应用程序,请使用区域特定的格式以使代码可以在许多区域之间移植。
到目前为止,已经介绍了字面值、位置和两种备选项操作符。仅使用这些内容,就可以匹配大多数具有可预测 长度的模式。现在回到用户名,通过以下 regex 命令可以确保每个用户名以字母开头并紧跟恰好七个字母或数字:
[a-z][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9][a-z0-9] |
但是这样有点笨拙。而且,它只匹配恰好八个字符的用户名。它不会匹配三到八个字符之间的名称,这通常也是有效的用户名。
正则表达式还可以包括重复修饰符。重复修饰符可以指定数量,如没有、一个、多个、一个或多个,零或一个、五到十个,以及恰好三个。重复修饰符必须与其他模式组合,修饰符本身没有含义。
例如,regex:
^[A-z][A-z0-9]{2,7}$ |
可以实现前面描述的用户名过滤功能。用户名 是以字母开头,后面紧跟至少两个,但不超过七个字母或数字的字符串,并且紧跟字符串结尾。
此处的位置定位点非常重要。如果没有两个位置操作符,则会错误地接受任意长度的用户名。为什么呢?请考虑 regex:
^[A-z][A-z0-9]{2,7} |
此命令辨别:字符串是否以字母开头并紧跟二到七个字母?但是它未提到终止条件。因此,字符串 samuelclemens 满足条件,但是它的长度显然超出了有效用户名的范围。与此类似,省略开始定位点 ^,或同时省略两个定位点将分别匹配以类似 munster1313 结束或包含该字符串的字符串。如果必须匹配特定的长度,请记得在要求的模式的开头和结尾分别加上分隔符。
以下是其他一些示例:
{2,} 查找两次或多次重复。regex ^G[o]{2,}gle 匹配 Google、Gooogle、Goooogle 等等。?、+ 和 * 分别查找零次或一次、一次或多次,以及零次或多次重复。(例如,您可以将 ? 看作是 {0,1} 的简写法。)regex boys? 匹配 boy 或 boys;regex Goo?gle 匹配 Gogle 或 Google。
regex Goo+gle 匹配 Google、Gooogle、Goooogle 等等。
construct Goo*gle 匹配 Gogle、Google、Gooogle 等等。
( 和 ) 圆括号(就像数学中的用法)将修饰符应用到子表达式。下面是一个示例:给定文本文件 test.txt: The rain in Spain falls mainly |
命令 grep -i -E '(\b(of|the)\W+){2,}' test.txt 将生成:
on the the plain. |
\b 匹配单词边界 或 (\W\w|\w\W)。该 regex 表示“一连串完整单词‘the’或‘of’后面紧跟非文字字符。”您可能会提出疑问,为什么 \W+ 是必需的:\b 是位于单词开头或结尾的空字符串。在单词之间必须包括这一(或这些)字符,否则该 regex 将无法找到匹配。查找文本是常见的问题,但是更常见的问题则是希望在找到文本之后将其提取出来。换句话说,您希望去粗取精。
正则表达式通过捕获 来提取信息。如果希望将需要的文本与其他内容分开,请使用圆括号将模式括起来。实际上,您已经使用圆括号收集术语;在默认情况下,圆括号自动进行捕获。
要查看捕获,请切换到 Perl。(grep 实用工具不支持捕获,因为其目标是打印包含模式的行。)
以下命令:
perl -n -e '/^The\s+(.*)$/ && print "$1\n"' heroes.txt |
将打印:
Tick |
使用命令 perl -e 可以直接从命令行运行 Perl 程序。perl -n 命令针对输入文件的每一行运行一次程序。命令的 regex 部分,即位于斜杠之间的文本(/)表示“匹配字符串的开头,然后字母‘T’、‘h’、‘e’后紧跟一个或多个空格字符 \s+,然后捕获直到字符串结尾的所有字符。
Perl 捕获内容被放在以 $1 开头的特殊 Perl 变量中。Perl 程序的其余部分打印捕获的内容。
每个嵌套的括号对,从左开始算起,每个左圆括号加一,放在下一个特殊的数字变量中。例如:
perl -n -e '/^(\w)+-(\w+)$/ && print "$1 $2"' |
将生成:
Spider Man |
捕获感兴趣的文本仅仅是隔靴搔痒。如果能够准确确定材料,就可以使用其他材料改变其外观。类似于 vi 和 Emacs 的编辑器将模式匹配与替换组合,从而将查找和替换文本组合成一步操作。还可以使用模式、替换和 sed 从命令行更改文本。
正则表达式非常强大;可供使用的操作符的数量庞大,种类繁多。它包含如此丰富的信息和实践知识,我们在这里所能列举的实属凤毛麟角。
幸运的是,有以下三种优秀的正则表达式理论来源可供使用:
perldoc perlre)。它会提供 regex 的精彩介绍,并包含许多有用的示例。许多编程语言都已采用 Perl 兼容的正则表达式 (PCRE),因此您在此 man 页面读到的内容已被直接转换到 PHP、Python、Java™ 和 Ruby 编程语言,以及许多其他最新工具。+ 和 * 匹配字符的数量),以及更多内容。此外,Friedl 的书还包括一些令人惊叹的正则表达式,可以准确地匹配完全限定的电子邮件地址和其他 Request for Comments (RFC) 特定的字符串。在命令行中,可以采用许多方法使用正则表达式。几乎每个处理文本的命令都支持某种形式的正则表达式。大多数 Shell 命令语法还或多或少地扩展正则表达式以匹配文件名(尽管操作符的功能可能有所不同)。
例如,键入 ls [a-c] 以查找名为 a、b 或 c 的文件。键入 ls [a-c]* 以查找以 a、b 或 c 开头的所有文件名。此处的 * 在 Shell 中不像 grep 的解释器那样修饰 [a-c],* 被解释为 .*。? 操作符在 Shell 中也可以工作,但是被解释为 .,即匹配任意单个字符。
查看您最喜欢的实用工具或 Shell 的文档以确定哪些 regex 操作符受支持,以及操作符可能具有的独特性。
这堂课比往常的时间要长。但是您现在已了解了正则表达式的基本知识。出去放松一下。
在您享受空闲的时候,我将开始编写很快会流行起来的经典歌词“描述 99 个命令的 99 行代码”。