【问题标题】:How can I write a long regular expression so it fits on the screen?如何编写一个长正则表达式使其适合屏幕?
【发布时间】:2009-06-22 07:55:05
【问题描述】:

我在 Perl 中有匹配正则表达式。 超过一行的匹配句子。

我意识到我必须在一行中输入匹配正则表达式,如果我传播 多行失败:

$array_11 =~ m{By Steve (.*), MarketWatch LONDON (.*) -- Shares of Anglo American rallied on Monday morning as (.*) bet that the mining group will reject a (.*)};'

如果我把它写成多行,它将无法匹配这个字符串。

【问题讨论】:

  • 为什么要调用标量变量 $array_11?
  • 你期望这个字符串“模式”有多少个独特的组合?

标签: regex perl code-formatting


【解决方案1】:

如前所述,您似乎正在寻找 x 修饰符。 该修饰符忽略正则表达式中的所有空格,并允许 cmets(以 # 开头)。

在你的情况下它有点难看,因为你必须替换所有空格 您确实想通过 [ ]、\s 或 \s+ 匹配正则表达式:

$array_11 =~ m{By \s+ Steve \s+ (.*), \s+
               MarketWatch \s+ LONDON \s+ (.*) \s+
               -- \s+ Shares \s+ of \s+ Anglo \s+ American \s+ 
               rallied \s+ on \s+ Monday \s+ morning \s+ as \s+ 
               (.*) \s+ bet \s+ that \s+ the \s+ mining \s+ 
               group \s+ will \w+ reject \w+ a \w+(.*)
              }x;

所以实际上我可能会这样写:

my $sentence= q{By Steve (.*), MarketWatch LONDON (.*) }
            . q{-- Shares of Anglo American rallied on Monday morning as (.*) }
            . q{bet that the mining group will reject a (.*)}
            ;
my $array_11=~ m{$sentence};

最后一条评论:$array_11 有强烈的代码味道,如果是数组,则将其设为数组,而不是多个标量变量。

【讨论】:

  • 使用 greedy 会得到大量的回溯。* 每次使用 .* 时,你都会吞下所有剩下的字符,然后回溯,直到你可以完成下一部分。非贪婪的 .*?至少会注意下一个序列。而且我不希望您期待“Steve MarketWatch,MarketWatch LONDON”,所以.*? explicit 让你想要注意其余的字符。
  • 过早的优化...好吧,你是对的,我并没有真正关注正则表达式的内容,也许我应该关注!将每个 .* 替换为 .*?效率会高很多。谢谢。
  • 你应该决定 .* 还是 .*?基于您希望在模棱两可的情况下匹配的内容,而不是更快的匹配。
  • @ysth:我想我也表达了这一点——当我说我怀疑他期待“Steve MarketWatch”序列时。这不仅仅是关于速度。这是一个健全的检查;它只包含速度问题。有点像:“select * from terabyte_table”是一个设计问题,也是一个优化。
【解决方案2】:

您可能正在寻找 /x 修饰符。

来自perldoc perlre

x 通过允许空格和 cmets 扩展模式的易读性。

【讨论】:

    【解决方案3】:

    所有逃逸的空间都非常丑陋和分散注意力。所以,这里有一个替代方案:

    my ($pattern) = map { qr/$_/ } join q{ }, split q{ }, <<'EOP';
        Steve (.*), MarketWatch LONDON (.*) --
        Shares of Anglo American rallied on Monday morning
        as (.*) bet that the mining group will \w+ reject
        \w+ a \w+(.*)
    EOP
    
    $text =~ $pattern;
    

    注意:我留下了 (.*),因为我不知道 OP 想要什么,但请参阅 Axeman 对 mirod's answer 的评论。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-06
      • 2020-11-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-30
      相关资源
      最近更新 更多