我一直喜欢的Linux终端之一是使用正则表达式可以实现的目标。 无论我们需要查找复杂的文本还是将其替换为其他文本,使用正则表达式都可以大大简化工作。 让我们从头开始:
什么是正则表达式?
正则表达式是一系列特殊字符,它们使我们能够描述我们要查找的文本。 例如,如果我们要搜索“ linux”一词,将其放入我们正在使用的程序中就足够了。 这个词本身是一个正则表达式。 到目前为止,这似乎非常简单,但是如果我们想在某个文件中查找所有数字怎么办? 还是所有以大写字母开头的行? 在那种情况下,您再也不能简单地说了。 解决方案是使用正则表达式。
正则表达式与文件模式。
在讨论正则表达式这一主题之前,我想消除对正则表达式的常见误解。 正则表达式不是我们在rm,cp等命令中作为参数来引用硬盘驱动器上各种文件的内容。 那将是一个文件模式。 正则表达式尽管相似,因为它们使用一些公共字符,但它们有所不同。 对硬盘上的文件触发文件模式,并返回与该模式完全匹配的文件,而对文本触发正则表达式,并返回包含搜索到的文本的行。 例如,对应于模式的正则表达式 *.*
就像 ^.*\..*$
正则表达式的类型。
并非所有程序都使用相同的正则表达式。 不多。 或多或少有几种标准类型的正则表达式,但是有些程序会稍微改变语法,包括它们自己的扩展名,甚至使用完全不同的字符。 因此,当您想对不熟悉的程序使用正则表达式时,第一件事是查看程序的手册或文档,以了解其可以识别的正则表达式。
首先,正则表达式有两种主要类型,它们包含在POSIX标准中,这是Linux工具使用的。 它们是基本和扩展的正则表达式。 使用正则表达式的许多命令(例如grep或sed)都可以使用这两种类型。 我将在下面谈论它们。 也有PERL样式的正则表达式,然后还有诸如vim或emacs之类的程序使用它们的变体。 根据我们要执行的操作,使用其中一个可能更合适。
测试正则表达式。
正则表达式的语法并不简单。 当我们不得不编写一个复杂的正则表达式时,我们将乍一看无法理解的特殊字符字符串,因此,要学习如何使用它们,必须有一种方法来进行我们想要并看到的所有测试结果容易。 这就是为什么我现在要放置几个命令,以便可以进行测试和实验所需的一切,直到以正则表达式为主导。
第一个是grep命令。 这是我们最常用于搜索的命令。 语法如下:
grep [-E] 'REGEX' FICHERO
COMANDO | grep [-E] 'REGEX'
我建议始终将正则表达式放在单引号中,以使外壳程序不适应它。 第一种方法是在文件中查找正则表达式。 第二个允许通过正则表达式过滤命令的输出。 默认情况下,grep使用基本正则表达式。 -E选项用于使用扩展的正则表达式。
可以帮助我们了解正则表达式如何工作的一个技巧是在grep命令中启用color的使用。 这样,与我们使用的正则表达式匹配的文本部分将突出显示。 要在grep命令中激活颜色,只需确保环境变量 GREP_OPTIONS
包含价值 --color
,可以使用以下命令完成:
GREP_OPTIONS=--color
我们可以将其放在.bashrc中以使其始终处于激活状态。
使用正则表达式的另一种方法是使用sed命令。 这更适合替换文本,但也可以用于搜索。 语法如下:
sed -n[r] '/REGEX/p' FICHERO
COMANDO | sed -n[r] '/REGEX/p'
缺省情况下,sed命令还使用基本正则表达式,可以将扩展正则表达式与-r选项一起使用。
我也想命名的另一个命令是awk。 此命令可用于许多用途,因为它允许您使用自己的编程语言编写脚本。 如果我们要在文件或命令的输出中查找正则表达式,则使用方式如下:
awk '/REGEX/' FICHERO
COMANDO | awk '/REGEX/'
此命令始终使用扩展的正则表达式。
为了进行测试,我们还需要一个文本作为搜索示例。 我们可以使用以下文本:
- Lista de páginas wiki: ArchLinux: https://wiki.archlinux.org/ Gentoo: https://wiki.gentoo.org/wiki/Main_Page CentOS: http://wiki.centos.org/ Debian: https://wiki.debian.org/ Ubuntu: https://wiki.ubuntu.com/ - Fechas de lanzamiento: Arch Linux: 11-03-2002 Gentoo: 31/03/2002 CentOs: 14-05-2004 03:32:38 Debian: 16/08/1993 Ubuntu: 20/10/2004 Desde Linux Rulez.
这是我将在其余文章的示例中使用的文本,因此,我建议您将其复制到文件中,以从终端获得。 您可以输入所需的名称。 我称它为正则表达式。
开始上课。
现在,我们拥有开始测试正则表达式所需的一切。 让我们一点一点走。 我将举几个带有正则表达式的搜索示例,在这些示例中,我将解释每个字符的作用。 它们不是很好的例子,但是由于我将要发表一篇很长的文章,所以我不想再复杂化了。 我只是想简单介绍一下正则表达式可以完成的工作。
最简单的方法是搜索一个特定的单词,例如,假设我们要查找包含单词“ Linux”的所有行。 这是最简单的,因为我们只需要写:
grep 'Linux' regex
我们可以看到结果:
拱Linux:https://wiki.archlinux.org/ Arch Linux:11年03月2002日来自 Linux Rulez。
这是包含单词“ Linux”的三行,如果使用了颜色技巧,它们将突出显示。 请注意,即使它是“ ArchLinux”中更长的单词的一部分,它也可以识别我们正在寻找的单词。 但是,它不会突出显示URL“ https://wiki.archlinux.org/”中出现的单词“ linux”。 那是因为它在那里以小写字母“ l”出现,而我们一直在寻找大写字母。 grep命令具有用于此的选项,但我不会在有关正则表达式的文章中讨论它们。
通过这个简单的测试,我们可以得出第一个结论:
- 放在正则表达式中的普通字符会与自己匹配。
也就是说,如果您输入字母“ a”,它将寻找字母“ a”。 看来合乎逻辑,对吧? 🙂
现在假设我们要搜索单词“ CentO”,后跟任何字符,但只有一个字符。 为此,我们可以使用“。”字符,这是一个与任何字符匹配的通配符,但只能匹配一个:
grep 'CentO.' regex
结果是:
CentOS的:http://wiki.centos.org/ 中心: 14-05-2004 03:32:38
这意味着它在“ CentOS”中包含“ S”,尽管在一种情况下为大写,在另一种情况下为小写。 如果在该位置出现了其他任何字符,也将包括该字符。 我们已经有了第二条规则:
- 人物 ”。” 匹配任何字符。
它不再像看起来那样琐碎,但是以此我们不能做太多事情。 让我们更进一步。 假设我们要查找2002和2004年出现的行,它们看起来像是两次搜索,但是可以像这样一次完成:
grep '200[24]' regex
这意味着我们要找到数字200,后跟2或4。结果是:
Arch Linux:11-03-2002 Gentoo:31/03 /2002 中心:14-05-2004 03:32:38 Ubuntu: 20/10/2004
这将我们带到第三条规则:
- 括号内的多个字符与括号内的任何字符匹配。
括号给了更多的发挥。 它们也可以用于排除字符。 例如,假设我们要查找出现“:”字符但不跟“ /”的站点。 该命令将如下所示:
grep ':[^/]' regex
只需将“ ^”作为括号中的第一个字符即可。 您可以将所有想要的字符放在下面。 最后一条命令的结果如下:
ArchLinux的: https://wiki.archlinux.org/ Gentoo: https://wiki.gentoo.org/wiki/Main_Page CentOS: http://wiki.centos.org/ Debian: https://wiki.debian.org/ Ubuntu: https://wiki.ubuntu.com/ Arch Linux: 11年03月2002日Gentoo: 31年03月2002日CentO: +14-05-2004 03:32:38 Debian: 16年08月1993日Ubuntu: 20/10/2004
现在,突出显示发行版名称后面的“:”,但突出显示了URL中的名称,因为URL后面带有“ /”。
- 将“ ^”字符放在方括号的开头可匹配除方括号中的其他字符以外的任何字符。
我们可以做的另一件事是指定字符范围。 例如,要搜索后跟“-”的任何数字,它将看起来像这样:
grep '[0-9]-' regex
这样,我们指定了一个介于0到9之间的字符,然后是一个负号。 让我们看一下结果:
Arch Linux:11-03-2002个CentO:1个4-05-2004 03:32:38
您可以在方括号内指定多个范围,甚至将范围与单个字符混合。
- 在方括号中放置两个用“-”分隔的字符会匹配该范围内的任何字符。
现在让我们看看是否可以选择URL的第一部分。 说“ http”或“ https”的那个。 它们仅在最后的“ s”中有所不同,因此我们如下进行操作:
grep -E 'https?' regex
问号用于使字符左侧成为可选字符。 但是现在我们在命令中添加了-E选项。 这是因为询问是扩展正则表达式的功能。 到目前为止,我们正在使用基本的正则表达式,因此我们不需要放入任何内容。 让我们看一下结果:
ArchLinux: HTTPS://wiki.archlinux.org/ Gentoo: HTTPS://wiki.gentoo.org/wiki/Main_Page CentOS: HTTP://wiki.centos.org/ Debian: HTTPS://wiki.debian.org/ Ubuntu: HTTPS://wiki.ubuntu.com/
因此,我们已经有了一条新规则:
- 字符后跟“?” 匹配该字符或不匹配。 这仅对扩展的正则表达式有效。
现在我们将找到两个完全不同的词。 让我们看看如何查找同时包含单词“ Debian”和“ Ubuntu”的行。
grep -E 'Debian|Ubuntu' regex
使用竖线,我们可以分隔两个或更多不同的正则表达式,并找到与它们中的任何一个匹配的行:
Debian:https://wiki.debian.org/ Ubuntu:https://wiki.ubuntu.com/ Debian:16 / 08 / 1993 Ubuntu:20 / 10 / 2004
- 字符«|» 用于分隔多个正则表达式并与它们中的任何一个匹配。 它也特定于扩展的正则表达式。
让我们继续。 现在,我们将寻找单词“ Linux”,但仅在不粘在左侧另一个单词的地方。 我们可以这样做:
grep '\
这里的重要字符是“ <”,但是需要通过在其前面加上“ \”来使其转义,以便grep将其解释为特殊字符。 结果如下:
拱 Linux:11年03月2002日来自 Linux Rulez。
您也可以使用“ \>”搜索彼此相邻的单词。 让我们来看一个例子。 让我们尝试以下命令:
grep 'http\>' regex
它产生的输出是这样的:
CentOS的: HTTP://wiki.centos.org/
出现了“ Http”,但没有出现“ https”,因为在“ https”中,“ p”右边仍然有一个字符,可以作为单词的一部分。
- 字符“ <”和“>”分别与单词的开头和结尾匹配。 这些字符必须转义,以便不被解释为文字字符。
我们处理的事情要复杂一些。 “ +”字符与其左侧的字符匹配,至少重复一次。 该字符仅在扩展的正则表达式中可用。 有了它,我们可以搜索例如以“:”开头的几个连续数字的序列。
grep -E ':[0-9]+' regex
结果:
中心:14年05月2004日03:32:38
数字38也被突出显示,因为它也以“:”开头。
- “ +”字符与其左侧的字符匹配,至少重复一次。
您也可以使用“ {”和“}”控制重复次数。 想法是在括号中加上一个数字,该数字指示我们想要的确切重复次数。 您还可以放置一个范围。 让我们看看这两种情况的例子。
首先,我们将找到所有四位数的序列:
grep '[0-9]\{4\}' regex
请注意,如果使用基本正则表达式,则必须对大括号进行转义,而如果使用扩展正则表达式,则不能。 扩展后将是这样的:
grep -E '[0-9]{4}' regex
两种情况的结果都是这样的:
Arch Linux:11-03-2002 Gentoo:31/03 /2002 中心:14-05-2004 03:32:38 Debian: 16/08/1993 Ubuntu的:20/10 /2004
- 字符“ {”和“}”之间的数字与重复指定次数的前一个字符相匹配。
现在是带有括号的另一个示例。 假设我们要查找包含3到6个小写字母的单词。 我们可以执行以下操作:
grep '[a-z]\{3,6\}' regex
结果将是这样的:
- LISTA de 页s 维基: 至RCHL操作系统: HTTPS:/ /维基.ArchLinux的.组织结构/ G恩图: HTTPS:/ /维基.gentoo.组织结构/维基/M艾因_P年龄 CENTOS: HTTP:/ /维基.CentOS的.组织结构/ D埃比安: HTTPS:/ /维基.Debian的.组织结构/ 要么暴动: HTTPS:/ /维基.Ubuntu的.COM/ - F你想念 de 发射: 至RCH L操作系统:11年03月2002日G恩图:31年03月2002日CENTOs: 14-05-2004 03:32:38 D埃比安:16年08月1993日暴动:20年10月2004日D它是 L操作系统 R乌列兹.
正如您所看到的,这看起来与我们想要的不一样。 这是因为正则表达式会在更长的其他单词中找到字母。 让我们尝试其他版本:
grep '\<[a-z]\{3,6\}\>' regex
结果:
-页面清单 维基:ArchLinux: HTTPS:/ /维基.archlinux。组织结构/ Gentoo: HTTPS:/ /维基.gentoo.组织结构/维基/ Main_Page CentOS: HTTP:/ /维基.CentOS的.组织结构/ Debian: HTTPS:/ /维基.Debian的.组织结构/ Ubuntu: HTTPS:/ /维基.Ubuntu的.COM/
这看起来更像我们想要的。 我们要做的是要求单词在第一个字母之前开始,而在最后一个字母之后结束。
- 字符“ {”和“}”之间有两个数字,中间用逗号隔开,该字符与前一个字符重复的次数由两个数字指示。
现在让我们看一下以“ +”开头的字符。 它是“ *”,其操作非常相似,只不过它匹配任意数量的字符,包括零。 也就是说,它的作用与“ +”相同,但不需要字符左侧出现在文本中。 例如,让我们尝试寻找那些以Wiki开始并以org结尾的地址:
grep 'wiki.*org' regex
让我们看一下结果:
ArchLinux:https://wiki.archlinux.org/ Gentoo:https://wiki.gentoo.org/ wiki / Main_Page CentOS:http://wiki.centos.org/ Debian:https://wiki.debian.org/
完善。
现在,我们要看到的最后一个字符。 “ \”字符用于使字符向右转义,从而失去其特殊含义。 例如:假设我们要找到以点结尾的线。 我们可能发生的第一件事可能是:
grep '.$' regex
结果不是我们想要的:
-维基页面列表: ArchLinux:https://wiki.archlinux.org/ Gentoo:https://wiki.gentoo.org/wiki/Main_Page CentOS:http://wiki.centos.org/ Debian:https://wiki.debian.org/ Ubuntu的:https://wiki.ubuntu.com/ -发布日期:Arch Linux:11年03月200日2 Gentoo:31/03/2002 CentOs: 14-05-2004 03:32:38 Debian:16/08/1993 Ubuntu的:20/10/2004 Desde Linux 鲁兹.
这是因为“。” 匹配任何东西,以便正则表达式匹配每行的最后一个字符,无论它是什么。 解决方案是这样的:
grep '\.$' regex
现在的结果就是我们想要的:
Desde Linux 鲁兹.
比赛结束
尽管正则表达式的主题是如此复杂,以至于我会写一系列文章,但我认为我已经给您带来了很多痛苦。 如果您成功到达,那么恭喜您。 如果您一口气阅读了所有这些内容,请服用阿司匹林或其他药物,因为效果不好。
现在就这些。 如果您喜欢这篇文章,也许我可以写另一篇。 同时,建议您尝试终端中的所有正则表达式,以清楚地了解它们的工作方式。 请记住:只有Chuck Norris才能使用正则表达式解析HTML。
没有正则表达式,我们的生活会怎样?
这篇文章非常有用,但是我会一点一点地阅读它。 非常感谢。
感谢您的评论。 我仍然不相信我的文章已经发表。 🙂它出现了一些错误,但我希望它是有用的。 🙂
谢谢youssssssss!..
一段时间以前,我不得不学习一些有关正则表达式的知识....感谢您的教学..以及有关逐步学习每一种表达式的逐步指南。
很好!...我要买阿司匹林..ee
别客气。 勇气,正则表达式不能与您同在。 🙂
很棒的帖子! 很好。 我想知道你花了几个小时😀
大声笑!! 问题是:如果我说完我想说的一切,我要花几个小时? 无穷 !! 🙂
一件事我不知道,好文章!
谢谢。 很高兴与您分享。
很好的解释。 恭喜,真的有用!
很高兴您发现它有用。 所以很高兴写
这应该特别。 喜欢精选但有非常具体的用途。 非常有用,尽管我希望看到它适用于Vim。
这是一个问自己的问题。 我想到了更多关于正则表达式的文章。 我可以谈谈其中的vim。 它与我在本文中解释的内容有所不同。 这是继续下去的问题。 🙂
好!
你的文章非常好,很有趣,最近(现在)我在我的网站上发布了一个我准备了几天的条目,其中我收集了正则表达式的元字符列表和一些示例。进入是公平的 DesdeLinux 并查看同一主题的条目!
如果有什么安慰的话,我的猫就更多了
当然,正则表达式是最有用的东西之一,例如,我通常使用它们来修剪命令的输出并保留我感兴趣的部分,然后在bash脚本中与之交互。 我在大学里也经常使用它们,它们对于编译器的构造(在字典和解析器的定义中)至关重要。 简而言之,整个世界。
问候和非常非常好的工作。
非常感谢。
我也喜欢你的文章。 它比我的要简洁。 它可以作为快速参考。 我们同时写了它们是一个巧合。 您可以看到人们对该主题感兴趣。 🙂
傻瓜的正则表达式=),现在让我更清楚了,一种为grep输出带有颜色的方法是在.bashrc中创建一个别名grep ='grep –color = always',以防万一。为某人工作。
问候
真正。 这是另一种方式。 感谢您的输入。 🙂
O_O…一份贡献! O_O ...
非常感谢您的帖子,我在等待类似的笑声已经有一段时间了,我将其打开以便在家中安静地阅读它,零麻烦来集中笑声。
谢谢你的文章,我真的很😀
我知道你会喜欢的大声笑!! 事实是,很多事情都遗漏了,但我已经想到了第二部分。 🙂
很棒的文章,只要我昨天读过,对我的学生来说,今天我上的课将会更加轻松!
大声笑!! 太糟糕了,我迟到了,但很高兴能为您提供帮助。 🙂
终于!!!,超棒的帖子....我终于找到了可以清楚解释正则表达式的内容... ..
那里有很多信息,但是要找到易于理解的东西却更加困难。 我很高兴填补了这一空白。 🙂
问候。
嘿,我需要帮助,我必须在/ var /日志中进行以下搜索:yymmdd,日志类似于130901.log -130901.log,我必须搜索1月11日至XNUMX月之间的所有日志XNUMX,我唯一要做的就是删除整个XNUMX月,但我不知道如何完成整个链条:
例如:1309 [0-3]会将1月30日至1日之间的日志返回给我,但我不知道如何从11月XNUMX日至XNUMX日也进入同一链。
使用正则表达式执行此操作有点复杂。 我想到这样的事情可能会起作用:
13(09[0-3]|10(0|1[01]))
它是扩展的正则表达式。 您没有说您正在使用哪个工具,所以我不能给您更多细节。
无论如何,我认为是这种情况,而不是使用正则表达式,最好使用find进行。 您可以尝试如下操作:
找。 -newermt '01 Sep'-a! -newermt '11 oct'-打印
运气。 希望这可以帮到你。
您好!首先,我要感谢您的工作,因为此页面在我最好的Linux站点的“前3名”之内。
我正在练习,但不知道为什么电话号码上的RegExp对我不起作用,原因是我错过了“ -E”(这要归功于这篇文章)。
我想问你,如果您不熟悉RegExp上的练习的不错的pdf或站点,尽管稍加想象就可以自己练习发明它们。
问候,巴勃罗。
很好,我已经读完了,是的,现在我需要阿司匹林
我见过的关于正则表达式的最好解释。 感谢作者分享这项工作。
问候。
我真的很喜欢一个很好的解释