我想从放置在 ()
括号中的文本文件中打印比一对括号更深的句子。
例如这个文本文件:
blabla(nothing(print me)) nanana (nanan)
blablabla(aaaaaaa(eeee(bbbb(cccc)bbb))aa)
blabla (blabla(hhhhh))
输出应该是:
print me
eeee(bbbb(cccc)bbb)
bbbb(cccc)bbb
cccc
hhhhh
这是我到目前为止所做的:
#!/usr/bin/perl -w
open(FILE, "<", $ARGV[0]) or die "file open error";
if ( @ARGV ) #if there are args
{
if ( -f $ARGV[0] ) #if its regular file
{
while(<FILE>)
{
my @array = split('\)',$_);
foreach(@array)
{
if ($_ =~ /.*\((.*)/)
{
print "$1\n";
}
}
}
close(FILE);
}
else{
print "Arg is not a file\n";}
}
else{
print "no args\n";}
我的代码无法分隔放在更深括号中的句子。
最佳答案
假设括号是平衡的:
use strict;
use warnings;
my @a;
while (<DATA>) {
while (/\(([^()]*(?:\(((?1))\)[^()]*(?{push @a, $2}))*+)\)/g){}
}
print join "\n", @a;
__DATA__
blabla(nothing(print me)) nanana (nanan)
blablabla(aaaaaaa(eeee(bbbb(cccc)bb(xxxx)b))aa)
blabla (blabla(hhhhh))
它返回:
print me
cccc
xxxx
bbbb(cccc)bb(xxxx)b
eeee(bbbb(cccc)bb(xxxx)b)
hhhhh
想法是在每次递归后存储捕获组 2 的内容,使用 (?{...})
构造来执行模式中的代码。
请注意,结果的顺序并不理想,因为最里面的内容最先出现。不幸的是,我没有找到改变结果顺序的方法。
图案细节:
\( # opening bracket level 1
( # open capture group 1
[^()]* # all that is not a bracket
(?:
\( # opening bracket for level 2 (or more when a recursion occurs)
( # capture group 2: to store the result
(?1) # recursion
)
\) # closing bracket for level 2 (or more ...)
[^()]* #
(?{push @a, $2}) # store the capture group 2 content in @a
)*+ # repeat when needed
)
\) # closing bracket level 1
编辑:此模式假设括号是平衡的,但如果不是这样,这可能会导致某些字符串出现不需要的结果的问题。原因是结果是在整个模式成功之前存储的。
带有字符串 1234 ( 5678 (abcd(efgh)ijkl)
的示例,其中缺少右括号:
1234 ( 5678 (abcd(efgh)ijkl)
# ^ ^---- second attempt succeeds, "efgh" is stored
# '---- first attempt fails, but "efgh", "abcd(efgh)ijkl" are stored
要解决此问题,您可以在两种默认行为之间进行选择:
- 只接受平衡括号的严格行为。您所需要做的就是将结果存储在一个临时数组中,并在 while 循环中或在缺少右括号时重置该数组。在这种情况下,结果将仅为
"efgh"
:
my @a;
my @b;
while (<DATA>) {
while (/\(([^()]*(?:\(((?1))\)[^()]*(?{push @b, $2}))*+)(?:\)|(?{undef @b})(*F))/g) {
push @a, @b;
undef @b;
}
}
- 一种更宽容的行为,不会强制使用右括号。为此,您必须将每个
\)
替换为(?:\)|$)
。在这种情况下,第一次尝试成功并消耗字符直到字符串结束(换句话说,没有第二次尝试)。结果是"efgh"
和"abcd(efgh)ijkl"
关于regex - 如何找到嵌套深度超过一个括号 '()' 集的句子?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37038927/