【问题标题】:Using Regexp::Common to get matched parenthesis, without the parenthesis使用 Regexp::Common 获得匹配的括号,不带括号
【发布时间】:2015-06-13 08:55:26
【问题描述】:

这是一个小问题,但我担心我在做傻事。我正在使用 Regexp::Common 来匹配匹配的括号正则表达式,但我需要括号的 contents,而不是整个表达式。所以我最终存储了一个临时字符串,对该字符串执行匹配后替换以摆脱括号,然后继续前进。所以想象一下我在“sphincter(arg1,arg2)”这一行上运行以下脚本(我正在写一个最小的例子,所以我希望它是可以理解的)。

 use Regexp::Common;
 $PAREN_EXP = $RE{balanced}{-parens=>'()'};
 $line =~ /foo$PAREN_EXP/; 
 $temp = $1;  temp now stores (arg1,arg2)
 $temp =~ s/\((.*)\)/$1/; # temp is now arg1,arg2
 $line =~/(.*)\($temp\)/close\($1,$temp\)/; 

结果该行现在是“close(sphinter, arg1, arg2)”,加上或减去我在执行示例时所犯的任何错误。现在这对我来说没问题,但我经常这样做,我想知道是否有更简单的方法?有没有办法让 Regexp::Common 库只给我内容?有没有办法让我定义 $PAREN_EXP 让它给我我喜欢的东西?有人看到更好的方法吗?

更好是指更小而不变成只写代码。

【问题讨论】:

  • 这感觉像是一个 XY 问题。你想达到什么目的? meta.stackexchange.com/questions/66377/what-is-the-xy-problem
  • Regexp::Common::balanced 当您可以嵌套括号时会有所帮助,但您的示例只有一对:(arg1,arg2) 如果您的数据不包含嵌套括号,我会这样做使用单个替换,例如:s/ (.*) \( (.*) \) /close($1,$2)/x。您可以使用 x 修饰符来忽略 LHS 上的空格,这样您就可以将内容隔开以提高可读性,甚至可以将它们拆分为多行并添加 cmets。您还可以使用命名捕获来阐明每个捕获组的作用,例如s/ (?<func> .*) \( (?<args> .*) \) /close($+{func},$+{args})/x;
  • 我的例子只是我能想出的最简单的例子来说明我的问题。我认为很明显,我只在有意义的情况下才对这样做感兴趣。显然情况并非如此。我正在替换复杂的 C++ 表达式,例如 foo(几个参数经常与嵌套括号的任意深度),而我正在做的事情解决了这个问题——我还可以编写递归解析或递归正则表达式,但到目前为止,这已被证明是最方便的。
  • @Spacemoose 请edit您的问题包括您实际使用的输入示例和预期输出。
  • @ThisSuitsBlackNot:是的,我可能不会——你为什么不从不同的角度考虑这个问题:Perl 有一个我觉得在很多情况下都非常有用的模块。如果我可以使用与非常稀疏的文档提供的稍微不同的方式,我会发现它会更好,我想知道是否有人知道如何做我想做的事情。不知道的人不要担心,这个问题不是针对你的。

标签: regex perl


【解决方案1】:

Regexp::Common::balanced 不能这样做,因为它生成的正则表达式只包含一个捕获组,它包含最外面的一组括号:

$ perl -MRegexp::Common=balanced -E 'say $RE{balanced}{-parens=>"()"}'
(?^:((?:\((?:(?>[^\(\)]+)|(?-1))*\))))
    ^                               ^
    |                               |
    +-------------HERE--------------+

幸运的是,Regexp::Common 允许您使用define your own regexes,因此您可以使用方便的$RE{foo} 语法:

use strict;
use warnings;
use 5.010;

use Regexp::Common qw(pattern);

pattern name   => [qw(inside_parens)],
        create => q/(?x: ( \( ( (?: (?> [^()]+ ) | (?-2) )* ) \) ) )/
        ;

say $2 if 'foo(bar(baz,bat), qux())' =~ /foo$RE{inside_parens}/;

输出:

bar(baz,bat), qux()

整个括号表达式存储在$1中,而括号的内容存储在$2中。

此正则表达式是 perldoc perlre 中描述的 matching balanced parentheses 的略微修改版本。

【讨论】:

  • 我想说声谢谢,即使输入框告诉我这里不适合这样做。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-03
  • 2018-03-06
相关资源
最近更新 更多