正则表达式——环视

环视

待匹配文本:

js 复制代码
THE RIME OF THE ANCYENT MARINERE, IN SEVEN PARTS.
ARGUMENT.
How a Ship having passed the Line was driven by Storms to the cold Country towards the South Pole; and how from thence she made her course to the tropical Latitude of the Great Pacific Ocean; and of the strange things that befell; and in what manner the Ancyent Marinere came back to his own Country.
I.
       It is an ancyent Marinere,
        And he stoppeth one of three:
       "By thy long grey beard and thy glittering eye
        "Now wherefore stoppest me?

1、正前瞻

假设要匹配单词ancyent,且要求紧随其后的单词是marinere(为与文件中的单词一致,我采用了古代拼写法)​。要达到这个目的,我们可以使用正前瞻。

首先在RegExr桌面版程序中试一下。将下面这个不区分大小写的模式输入到顶部的文本框内:

js 复制代码
(?i)ancyent(?= marinere)

由于我们使用了不区分大小写的选项(? i)​,就不必担心模式中用的大小写形式了。现在就是在每一行中寻找后跟marinere的单词ancyent。结果会在模式区域下面的文本区中标亮​;但只有模式的第一部分(ancyent)是被标亮的,环视模式(Marinere)不会标亮。

现在使用Perl来做正前瞻。你可以写这样一个命令:

现在使用Perl来做正前瞻。你可以写这样一个命令:

bash 复制代码
perl -ne 'print if /(?i)ancyent(?= marinere)/' rime2.txt

其输出如下:

js 复制代码
THE RIME OF THE ANCYENT MARINERE, IN SEVEN PARTS.
How a Ship having passed the Line was driven by Storms to the cold Country
towards the South Pole; and how from thence she made her course to the tropical
Latitude of the Great Pacific Ocean; and of the strange things that befell;
and in what manner the Ancyent Marinere came back to his own Country.
      It is an ancyent Marinere,
      "God save thee, ancyent Marinere!
      "I fear thee, ancyent Marinere!

该诗有五行内容中的ancyent出现在marinere之前。如果要求ancyent之后的单词以大写或小写字母m开头,该如何做呢?可以这样:

bash 复制代码
perl -ne 'print if /(?i)ancyent (? =m)/' rime.txt

现在除了Marinere,跟在后面的还可以有man和Man:

bash 复制代码
And thus spake on that ancyent man,
And thus spake on that ancyent Man,

ack也可以使用环视功能,这是因为它是由Perl语言编写的。ack的命令行界面与grep十分相似。

试一下这个命令:

bash 复制代码
ack '(? i)ancyent (? =ma)' rime.txt

试一下这个命令:

js 复制代码
ack '(? i)ancyent (? =ma)' rime.txt

你会看到高亮显示的结果,如图所示。

使用ack时,可以用命令行选项-i指定不区分大小写,而不使用嵌入选项(? i):

js 复制代码
ack -i 'ancyent (? =ma)' rime.txt

使用ack时,可以用命令行选项-i指定不区分大小写,而不使用嵌入选项(? i):

js 复制代码
ack -i 'ancyent (? =ma)' rime.txt

若要在ack的输出中添加行号以方便计数,可以采用多种方法。比如可以加上-H选项:

js 复制代码
ack -Hi 'ancyent (? =ma)' rime.txt

也可以添加带有--output选项的代码:

js 复制代码
ack -i --output '$.:$_' 'ancyent (? =ma)' rime.txt

这有点不太正统------关闭了标亮功能,但它确实起作用了。

2、反前瞻

反前瞻是对正前瞻的取反操作。这意味着要匹配某个模式时,需要在它后面找不到含有给定前瞻模式的内容。反前瞻的形式是:

bash 复制代码
(? i)ancyent (? ! marinere)

只有一个字符发生了变化:正前瞻的等号(=)变为反前瞻的感叹号(!)​。下图所示为在Opera中执行反前瞻查找。

在Perl语言中,可以这样来使用反前瞻:

bash 复制代码
perl -ne 'print if /(? i)ancyent (? ! marinere)/' rime.txt

而我们会得到的结果是:

bash 复制代码
And thus spake on that ancyent man,
And thus spake on that ancyent Man,

在ack中,可以用

bash 复制代码
ack -i 'ancyent (? ! marinere)' rime.txt

得到相同结果。

3、正后顾

正后顾会查看左边的内容,这与正前瞻方向相反。其语法是:

js 复制代码
(? i)(? <=ancyent) marinere

正后顾使用小于号(<)​,提醒你后顾是哪个方向。请在RegExr中试一下,看看有什么不同。被标亮的是marinere而不是ancyent。为什么?因为正后顾的模式是匹配的条件,不会包含在匹配结果中。

在Perl语言中这样做:

bash 复制代码
perl -ne 'print if /(? i)(? <=ancyent) marinere/' rime.txt

在ack中这样做:

bash 复制代码
ack -i '(? <=ancyent) marinere' rime.txt

4、反后顾

最后一种环视是反后顾。你能猜到它的工作原理吗?

反后顾会查看某个模式在从左至右的文本流的后面没有出现。同样,它有一个小于号(<)​,提醒后顾的是哪个方向。

请在RegExr中使用这个命令并查看结果:

bash 复制代码
(?1)(? <! ancyent) marinere

滚动到下方看看结果是什么。

然后用Perl语言尝试:

bash 复制代码
perl -ne 'print if /(? i)(? <! ancyent) marinere/' rime.txt

以下就是你会看到的结果,没有一个地方含有单词ancyent:

bash 复制代码
   The Marinere hath his will.
   The bright-eyed Marinere.
   The bright-eyed Marinere.
 The Marineres gave it biscuit-worms,
   Came to the Marinere's hollo!
   Came to the Marinere's hollo!
 The Marineres all 'gan work the ropes,
 The Marineres all return'd to work
 The Marineres all 'gan pull the ropes,
   "When the Marinere's trance is abated."
 He loves to talk with Marineres
 The Marinere, whose eye is bright,

最后在ack中这样做:

bash 复制代码
ack -i '(? <! ancyent) marinere' rime.txt

以上就是对前瞻和后顾的简单介绍,这是现代正则表达式的一个重要特性。

相关推荐
许彰午3 小时前
07-SqlBuilder六法
java·开发语言·低代码·架构
BS30813_vx3 小时前
【编号:01652】Spring Boot村务管理系统:财务公开、党建活动与计生服务一体化实战
开发语言·python
Jul1en_3 小时前
【Java 脚手架】封装通用工具类-3
java·开发语言·redis·缓存·ai·bootstrap·rabbitmq
学习星球3 小时前
2026年AI Agent全栈开发实战——从Prompt到Production
开发语言·人工智能·prompt
Fluxart.ai3 小时前
商品多角度图怎么做?Flux Art 从白底图到规格图、包装图的 10 步教程
开发语言·前端·javascript
captain3764 小时前
文件与IO(2)
java·开发语言·windows·java-ee
mqiqe4 小时前
AgentScope Java 2.0 集成 Chat Completions Web:一行依赖让你的 Agent 变身 OpenAI 兼容服务
java·开发语言·前端
qq_589666054 小时前
Java微服务介绍及应用
java·开发语言·微服务
uoKent5 小时前
c++中的extern关键字
开发语言·c++