【问题标题】:PERL: Using REGEX to match a string without the first token repeated in the string. (ABC, not AAA ABC)PERL:使用 REGEX 匹配字符串,而字符串中没有重复的第一个标记。 (ABC,不是 AAA ABC)
【发布时间】:2012-07-03 23:40:13
【问题描述】:

我对 perl 比较陌生,如果这个问题很简单并且我遗漏了一些完全明显的东西,我提前道歉,但是,我已经四处寻找答案几天了,但找不到解决方案。

我正在尝试使用正则表达式来匹配第一个实例,其中 A 后跟 C,而 A 和 C 之间没有另一个 A。请注意,在此文本字符串中,第一个 A.C 组合后面还有其他实例也可能适合A.C,(特别注意 ADC)这是文本:

$text = "AAA ABC ADE AFG ADC AHI AJK AIZ XXB NBV";

我第一次尝试:

@finds1=$TEXT=~m/(A.*?C)/;
$result = $finds1[0];
print "result = $result\n";

这将打印以下内容:

result = AAA ABC

当我想要的只是:

result = ABC

请注意,我正在尝试创建一个可以在 B 可以是任何字符串的情况下使用的正则表达式。例如 ADC、AFGHJKC、AYUIOKJHGTC。

接下来我尝试使用前瞻结合 if then else 语句。代码如下:

@finds1=$TEXT=~m/(A(?(?!.*?A.*?C).*?C|Z{100}))/;
$result = $finds1[0];
print "result = $result\n";

正则表达式 (A) 的第一部分告诉 perl 找到 A。一旦找到,perl 就会处理 if then else 语句,其中条件语句是没有 .?A .?A 跟在 A 之后,如果没有找到,则 perl 查找 .*?C,如果找到至少一个,则搜索 100 个 Z 实例。(我让 Perl 继续前进的方法是在这个文本和我试图解析的文本中都没有 100 Zs。)

这会返回:

result = ADC    

在第一次识别 C 之后,我考虑过使用积极的后视。但是,就像我上面提到的,第一个 A.C 组合之间没有 A 的字符数是可变的。据我所知,PERL 不能进行可变长度的后视。

非常感谢您提供的任何帮助或指导!!

提前致谢!

【问题讨论】:

  • 我对 /A[b-zB-Z]*?C/ 符合要求的解释有误吗?
  • 你是对的。它确实适用于此文本。感谢您的答复。您将如何修改它以适应 A 和 C 之间的空间(例如 $text = "AAA A B C ADE AFG ADC AHI AJK AIZ XXB NBV";
  • 在这里,我将对其进行扩展,使其值得回答,并在那里回答您的问题。
  • 像这样:/A\s*[b-zB-Z]*?\s*C/
  • 真的,完全没有理由这么复杂。 /A[b-zB-Z\s]*?C/ 也可以,而且要简单得多。

标签: perl


【解决方案1】:

你不想要

/A[^AC]*C/

【讨论】:

    【解决方案2】:

    据我所知,你想要的是:

    • 一个“A”
    • 后跟任意数量的非 A 字符
    • 后跟一个“C”

    这可以通过正则表达式来实现

    /A[B-Z]*?C/

    方括号[] 中的字符代表一个字符类。使用字符类,您可以告诉正则表达式引擎只匹配几个字符中的一个。只需将要匹配的字符(或字符范围)放在方括号 (http://www.regular-expressions.info/charclass.html) 之间。假设你想用另一个字母 Q 来做这件事,你会有一个稍微不同的字符类

    /Q[A-PR-Z]*?C/

    如果您想修改它以适应 A 和 C 之间的空间,您可以通过两种不同的方式来处理它。您可以否定一个字符类,它将匹配 任何 字符,除了其中的字符,如下所示:

    /A[^AC]*C/

    将匹配一个 A,然后匹配除 A 和 C 之外的任意数量的字符,然后是一个 C。

    或者,您可以在原始字符类中添加一个空格,如下所示:

    /A[B-Z ]*?C/(注意Z后面的空格)

    如果您想要任何类型的空格,请将空格替换为 \s,它表示任何空格,如下所示:

    /A[B-Z\s]*?C/

    【讨论】:

    • 感谢您的出色回答。你说的对。我的问题很简单。尽管您的回答回答了我如何表达我的问题,但它并不能完全解决我的问题。这完全是我的错。如果我将文本制作如下,更好的解决方法是:“$text = ate ate ate ate bat cat ate dog egg ate for gin ate dog cat ate;”现在,我不想提取 ABC,而是第一次提取 ate 之后是 cat,而 ate 和 cat 之间没有 ate。
    • 是的,那肯定更难!
    • 关于如何处理它的任何想法?你认为我应该用更新的文本发布一个新问题吗?再次感谢您的帮助。
    • 我会考虑的。我想我知道该怎么做,但它可能不是世界上最有效或最漂亮的正则表达式。
    • 在这一点上,我会拿出最丑陋的工作代码。
    猜你喜欢
    • 2023-03-29
    • 1970-01-01
    • 2013-03-11
    • 1970-01-01
    • 1970-01-01
    • 2018-06-15
    • 1970-01-01
    • 1970-01-01
    • 2023-03-12
    相关资源
    最近更新 更多