RegEx 问题 - Perl- 搜索字符串的最后一个实例

RegEx question- Perl- search for last instance of string

提问人:April Urban 提问时间:11/10/2023 最后编辑:zdimApril Urban 更新时间:11/12/2023 访问量:120

问:

对于所有正则表达式专家来说,这可能非常简单,但是我已经花了足够的时间让自己发疯,试图自己找到答案。

我使用 Doc Parser,它允许您创建文本解析规则。您可以使用正则表达式进行搜索。文档说支持 PERL 正则表达式,并且 Regex 101 站点是测试表达式的好地方,但我过去发现在 Regex 101 中起作用的表达式似乎并不总是在 Doc Parser 中起作用。

我正在尝试创建一个表达式来搜索三个字符串之一的最后一个实例。这三个字符串是:

i am sitting with after this meeting are
won't be included in your published notes
Single Signal

输入文本可以以三种不同的方式显示,这就是我寻找三个字符串之一的原因。这里有三个例子:

例 1:

Single Signal

Two things I am sitting with after this meeting are...

- Words words words

例 2:

Single Signal

- words words words

例 3:

Single Signal

words words that end in won't be included in your published notes.

- words

我捕捉到的三个短语最终成为我真正从文本中提取的内容的起点。

我将其用作我的核心/根表达式:

(?i)(i am sitting with after this meeting are|This is for internal
use and won't be included in your published notes|Single Signal)

并在表达式末尾尝试了各种方法,以指示匹配文本中最后/最晚发生的内容。

(?i)(i am sitting with after this meeting are|This is for internal
use and won't be included in your published notes|Single Signal).*?

(?i)(i am sitting with after this meeting are|This is for internal
use and won't be included in your published notes|Single Signal)+

(?i)(i am sitting with after this meeting are|This is for internal
use and won't be included in your published notes|Single Signal){1}

这在正则表达式 101、PCRE2 中有效,但在 Doc Parser (Perl) 中不起作用:

(?i)[^(i am sitting with after this meeting are|won't be included in your published notes|Single Signal)]+$

非常感谢所有的帮助。谢谢!

正则表达式 Perl

评论

0赞 Barmar 11/10/2023
我重新格式化了您的问题,以便您可以更好地查看字符串和示例。请确保我理解正确。
1赞 Barmar 11/10/2023
放在正则表达式的开头,而不是结尾。这将在匹配其中一个备选项之前跳过尽可能多的文本。.*
1赞 sln 11/10/2023
This worked in Regex101除非您发布指向它的链接,否则没有任何效果
0赞 April Urban 11/10/2023
@sln我不确定如何在 regex101.com 上发布测试链接。
0赞 sln 11/10/2023
保存正则表达式左上角按钮。复制链接。

答:

3赞 zdim 11/10/2023 #1

“全局”匹配 -- 查找字符串中的所有匹配项 -- 并捕获匹配项。然后正则表达式继续通过字符串,但当它进行时,它只能捕获当前匹配项,因此我们最终会得到最后一个匹配项。在 Perl 语法中

/(one|two|three)/g

这最终在捕获变量中具有与上次匹配的三个子模式中的任何一个匹配(在列表上下文中使用时)/

一个例子

my $text = q(hi one some two or three and two more);

my @captures = $text =~ /(one|two|three)/g;

# $1 == 'two'

(capture) 变量具有字符串 .(数组的最后一个元素也是如此,但我希望该工具无法创建变量并捕获到其中。$1two

对数组的赋值迫使正则表达式进入“列表上下文”,在该上下文中,它继续匹配整个字符串;因此,我们根据需要获得最后一次捕获。(不必实际分配给数组,以任何方式强制列表上下文就足够了。

我不知道“Doc Parser”是什么或它是如何工作的,所以我不知道如何强制该工具中使用的正则表达式变体的行为如上所述,但我认为这是可能的。

评论

1赞 jhnc 11/10/2023
@ChrisCharley我认为匹配需要在列表上下文中完成。例如:seq 20| perl -e '$/=undef; $_=<>; ()=/(3|13|19)/g; print $1'
0赞 zdim 11/11/2023
@jhnc 是的,但是我放弃了它的一部分(只是把它放回去),试图把它提炼成正则表达式——因为我希望“Doc Parser”(我不知道)可能无法使用任何编程语言的语言特性。由于它可以使用正则表达式,因此我假设它可以以某种形式使用捕获组。但是我不知道如何在该工具中确保匹配继续通过字符串,因此此处的想法的应用确实取决于工具......编辑。
0赞 zdim 11/12/2023
@AprilUrban 更新的答案(昨天)
0赞 April Urban 11/16/2023
谢谢你,这是有用的信息,帮助我更多地了解正则表达式,让我走上了正确的道路。
1赞 jhnc 11/11/2023 #2

如果在初始正则表达式前面加上 (或可能 ),则最多可以有一个匹配项,因此应捕获正确的值。.*.*\K

$ perl -e '
    $t = "1a 2a 3a 1b 2b 1c 3c 2d";
    $t =~ /.*(1.|2.|3.)/;
    print "matched $1\n" 
'
matched 2d
$

您可能需要进行调整,以便前缀也捕获换行符。

评论

1赞 April Urban 11/16/2023
感谢您的耐心等待,我是在 Stack Overflow 上写作的新手。我认为这是最接近正确答案的;添加对我有用的东西。我错了,它在Perl中。它在PCRE中。我需要将语句封装在 / 中,并以 / 结尾。我需要负面回溯和跨行功能。什么有效: /(?s:.*\s)\K(我在这次会议后坐在一起|包含在您发表的笔记中。|单信号)(?!.*(我和这次会议后坐在一起的是|你发表的笔记|单信号))/ 这有助于:xlayer.co.za/forum/viewtopic.php?id=105