perl 解析格式错误的括号文本
我有一串文本被分成短语,每个短语都用方括号括起来:
[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]
如何保留最后一个块?
I have a string of text chunked into phrases, with each phrase surrounded by square brackets:
[pX textX/labelX] [pY textY/labelY] [pZ textZ/labelZ] [textA/labelA]
Sometimes a chunk does not start with a p-character (like the last one above).
My problem is I need to capture each chunk. That's okay under normal circumstances, but sometimes this input is mis-formatted, for example, some chunks might have only one bracket, or none. So it might look like this:
[pX textX/labelX] pY textY/labelY] textZ/labelZ
But it ought to come out like this:
[pX textX/labelX] [pY textY/labelY] [textZ/labelZ]
The problem does not include nested brackets. After diving into loads of different people's regex solutions like never before (I'm new at regex), and downloading cheat-sheets and getting a Regex tool (Expresso) I still don't know how to do this. Any ideas? Maybe regex doesn't work. But how is this problem solved? I imagine it's not a very unique problem.
Edit
Here is a specific example:
$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";
This is a great compact solution from @FailedDev:
while ($data =~ m/(?:\[[^[]*?\]|[^[ ].*?\]|\[[^[ ]*)/g) { # matched text = amp; }
but I think two points need to be added for emphasis in the problem:
- some chunks have no brackets at all
- ,/PUNC and w#hm/CC_PRP_MP3] are separate chunks that need to be separated.
However, since this case is a fixed one (ie. a PUNCTUATION mark followed by a text/label pattern that has only one square bracket on the right), I kind of hard-coded it into the solution like this:
my @stuff;
while ($data =~ m/(?:\[[^[]*?\]|[^[ ].*?\]|\[[^[ ]*)/g) {
if(amp; =~ m/(^[\S]\/PUNC )(.*\])/) # match a "./PUNC" mark followed by a "phrase]"
{
@bits = split(/ /,amp;); # split by space
push(@stuff, $bits[0]); # just grab the first chunk before space, a PUNC
push(@stuff, substr(amp;, 7)); # after that space is the other chunk
}
else { push(@stuff, amp;); }
}
foreach(@stuff){ print $_; }
Trying the example I added in the edit, this works just fine except for one problem. The last ./PUNC gets left out, so the output is:
[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]
How can I keep the last chunk?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您可以使用这个
假设您的字符串类似于:
它不适用于例如:
pY [[[textY/labelY]
Perl 特定解决方案:
更新:
这适用于您更新的字符串,但是您如果需要的话,应该修剪结果的空白。
更新:2
我建议提出一个不同的问题,因为你原来的问题与上一个问题完全不同。
You could use this
Assuming your string is something like :
It will not work with this for example :
pY [[[textY/labelY]
Perl specific solution :
Update :
This works with your updated string, but you should trim the whitespace of the results, if you need to.
Update : 2
I suggest opening a different question, because your original question is totally different than the last one.
这基本上与我应用于您的上一个问题的过程相同,我只是更改了
地图
一点:您得到的输出是这样的(连字符只是为了说明缺少前导/尾随空格):
我认为这是您想要获得的结果。我不知道您是否会对非“仅限正则表达式”的解决方案感到满意......
This is essentially the same procedure which I applied to your previous problem, I just changed the
map
a bit:The output you get is this (the hyphens are only there to illustrate the absence of leading/trailing blanks):
I think this is the result you wanted to obtain. I don't know whether you will be satisfied with a non-'regex only' solution though...