【发布时间】:2011-11-18 19:33:47
【问题描述】:
我将一串文本分成多个词组,每个词组都用方括号括起来:
[pX textX/labelX] [pY textY/labelY] [pZ textZ/labelZ] [textA/labelA]
有时块不以 p 字符开头(如上面的最后一个)。
我的问题是我需要捕获每个块。这在正常情况下是可以的,但有时这个输入的格式是错误的,例如,一些块可能只有一个括号,或者没有。所以它可能看起来像这样:
[pX textX/labelX] pY textY/labelY] textZ/labelZ
但它应该是这样的:
[pX textX/labelX] [pY textY/labelY] [textZ/labelZ]
问题不包括嵌套括号。在以前所未有的方式深入研究大量不同人的正则表达式解决方案(我是正则表达式的新手),下载备忘单并获得正则表达式工具(Expresso)之后,我仍然不知道该怎么做。有任何想法吗?也许正则表达式不起作用。但是这个问题是如何解决的呢?我想这不是一个非常独特的问题。
编辑
这是一个具体的例子:
$data= "[VP sysmH/VBD_MS3] [PP ll#/IN_DET Axryn/NNS_MP] ,/PUNC w#hm/CC_PRP_MP3] [NP AEDA'/NN] ,/PUNC [PP b#/IN m$Arkp/NN_FS] [NP >HyAnA/NN] ./PUNC";
这是来自@FailedDev 的一个非常紧凑的解决方案:
while ($data =~ m/(?:\[[^[]*?\]|[^[ ].*?\]|\[[^[ ]*)/g) { # matched text = $& }
但我认为需要补充两点来强调这个问题:
- 有些块根本没有括号
- ,/PUNC 和 w#hm/CC_PRP_MP3] 是需要分开的独立块。
但是,由于这种情况是固定的(即,一个标点符号后跟一个右侧只有一个方括号的文本/标签模式),我将它硬编码到这样的解决方案中:
my @stuff;
while ($data =~ m/(?:\[[^[]*?\]|[^[ ].*?\]|\[[^[ ]*)/g) {
if($& =~ m/(^[\S]\/PUNC )(.*\])/) # match a "./PUNC" mark followed by a "phrase]"
{
@bits = split(/ /,$&); # split by space
push(@stuff, $bits[0]); # just grab the first chunk before space, a PUNC
push(@stuff, substr($&, 7)); # after that space is the other chunk
}
else { push(@stuff, $&); }
}
foreach(@stuff){ print $_; }
尝试我在编辑中添加的示例,除了一个问题外,它工作得很好。最后一个 ./PUNC 被遗漏了,所以输出是:
[VP sysmH/VBD_MS3]
[PP ll#/IN_DET Axryn/NNS_MP]
,/PUNC
w#hm/CC_PRP_MP3]
[NP AEDA'/NN]
,/PUNC
[PP b#/IN m/NN_FS]
[NP >HyAnA/NN]
我怎样才能保留最后一个块?
【问题讨论】:
-
这不是你之前的查询吗:HERE
-
没有。这仅适用于带或不带括号的块。这包括缺少一个括号和一个存在的块。
-
糟糕,我确实错了。我很抱歉。
标签: regex string perl parsing tags