У меня есть строка текста, разбитая на фразы, каждая фраза заключена в квадратные скобки:
[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]
Проблема не включает вложенные скобки. После погружения в множество различных решений regex, как никогда раньше (я новичок в regex), загрузки таблиц и получения инструмента Regex (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] - это отдельные фрагменты, которые необходимо разделить.
Однако, поскольку этот случай является фиксированным (т. Е. Метка PUNCTUATION, за которой следует шаблон текста / метки, который имеет только одну квадратную скобку справа), я как бы жестко закодировал его в решении, подобном этому:
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]
Как мне сохранить последний кусок?