Поиск повторяющихся теговых подстрок - PullRequest
3 голосов
/ 23 сентября 2019

У меня есть файл, в котором строки состоят из полей, которые:

  • Разграничены буквенно-цифровыми тегами, которые начинаются со специального символа ('%' в моем примере ниже)
  • Текст тега заканчивается пробелом
  • Содержимое поля заканчивается ','
  • Содержимое поля никогда не будет содержать % или ,

Пример строки:

% astuff,% b bstuff,% t это,% u это,% v это,% t это,% x другой,% xx только один раз,% q другой,% z другой,% c cstuff

Наборы тегов важны для поиска - это набор тегов для моего примера:

% t,% u,% v,% w,% x,% xx,% y,% z

Я хочу найти содержимое полей, гдетег находится в наборе, а содержимое поля повторяется в последующем поле, помеченном из набора.Вот код моей неудачной попытки:

my $tagmrkr='%';
my $line='%a astuff,%b bstuff,%t this,%u that,%v this,%t that,%x the other,%xx only once,%q the other,%z the other,%c cstuff';

my $searchtags = qr/t|u|v|w|x|xx|y|z/; # excludes q

print qq/The line:$line\n\n/;
for ($line =~ m/
    $tagmrkr$searchtags\ ([^\,]*,)
    .*?
    $tagmrkr$searchtags\ \1
    /gx) {
        print qq/First field contents:$1\n/;
        print qq/Entire match:$&\n/;
        print qq/\n/;
        }

Я ожидал:

The line:%a astuff,%b bstuff,%t this,%u that,%v this,%t that,%x the other,%xx only once,%q the other,%z the other,%c cstuff

First field contents:this,
Entire match:%t this,%u that,%v this,

First field contents:the other,
Entire match:%x the other,%xx only once,%q the other,%z the other,

Я получил:

The line:%a astuff,%b bstuff,%t this,%u that,%v this,%t that,%x the other,%xx only once,%q the other,%z the other,%c cstuff

First field contents:the other,
Entire match:%x the other,%xx only once,%q the other,%z the other,

First field contents:the other,
Entire match:%x the other,%xx only once,%q the other,%z the other,

Вопрос 1:
Почему$1 и $& для первого совпадения заменяются значениями из второго совпадения?

Вопрос 2: - Что я должен изменить, чтобы получить то, что я хочу (ниже) не то, что я ожидаю?

То, что я хочу, - это возможность повторного поворота совпадения, чтобы оно также находило повторяющееся поле, несмотря на перекрытия - где первое поле второго совпадения происходит довторое поле первого матча.На самом деле, для моих непосредственных целей все, что мне нужно, это дублированное содержимое поля.

Т.е. я хочу 3 совпадения из примера:

The line:%a astuff,%b bstuff,%t this,%u that,%v this,%t that,%x the other,%xx only once,%q the other,%z the other,%c cstuff

First field contents:this
Entire match:%t this,%u that,%v this,

First field contents:that
Entire match:%u that,%v this,%t that,

First field contents:the other
Entire match:%x the other,%xx only once,%q the other,%z the other,

Ответы [ 2 ]

3 голосов
/ 24 сентября 2019

Один из способов обеспечить перекрытия - это заявить о наличии остальной части фразы с предвкушением.Тогда эта часть не израсходована, и двигатель продолжает работать раньше, чем он, и поэтому он может соответствовать ей снова

use warnings;
use strict;
use feature 'say';

my $s = q(%a astuff,%b bstuff,%t this,%u that,%v this,%t that,)
      . q(%x the other,%xx only once,%q the other,%z the other,%c cstuff); 

my $m = qr/%/;
my $t = qr/(?:t|u|v|w|x|xx|y|z)/; 

while ($s =~ / $m$t \s ([^,]+) , (?=(.*?$m$t\s\g{1},?)) /gx) { 
    say "capture: $1";
    say "  whole: $1,$2";
}

Отпечатки

capture: this
  whole: this,%u that,%v this,
capture: that
  whole: that,%v this,%t that,
capture: the other
  whole: the other,%xx only once,%q the other,%z the other,
0 голосов
/ 23 сентября 2019

Использование глобального совпадения в цикле for вернет все совпадения сразу (и затем итерирует совпадения), следовательно, переменные совпадения будут установлены на последнее успешное совпадение (перед началом итерации), тогда как использованиеГлобальное соответствие регулярному выражению в условии while оценивает его в скалярном контексте, так что переменные соответствия будут правильными для каждой итерации.

Вы можете получить все три соответствия, сбросив pos $line для каждой итерации.Например, используя следующий подход:

while ($line =~ m/
      $tagmrkr$searchtags\ ([^\,]*,)
      .*?
      $tagmrkr$searchtags\ \1
   /gx) {
    pos $line = $-[0] + 1;
    print qq/First field contents:$1\n/;
    print qq/Entire match:$&\n/;
    print qq/\n/;
}

Вывод :

The line:%a astuff,%b bstuff,%t this,%u that,%v this,%t that,%x the other,%xx only once,%q the other,%z the other,%c cstuff

First field contents:this,
Entire match:%t this,%u that,%v this,

First field contents:that,
Entire match:%u that,%v this,%t that,

First field contents:the other,
Entire match:%x the other,%xx only once,%q the other,%z the other,
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...