Perl извлекает группу со взглядом из другой строки - PullRequest
1 голос
/ 05 апреля 2019

Я пробовал поиск в Интернете и прочитал несколько ответов на stackexchange, но до сих пор не могу понять, почему команда ничего не извлекает.В конце я хочу извлечь группу с lookbehind из другой строки, например, из

Code>TEST1<Code Code2>best<Code2
Code>test2<Code
Type>false<Type

, найдя необходимый ключ между Type и извлекая первую Code над находкой, так что это выше, чтобы получить test2.Но мне не удается извлечь даже что-то из нескольких строк, то есть

perl -lne 'print $1,"_",$2 if /Code>(.*)<Code[\s\S\n]*?Type>(.*)<Type/'<test.txt ничего не печатает.
Я играл с удалением ln параметров и добавлением / удалением жадного ? и пытаясь просто . вместо [\s\S\n].

perl -lne 'print $1,"_",$2 if /Code>(.*)<Code[\s\S\n]*?Code2>(.*)<Code2/'<test.txt дает TEST1_best так же работает извлечение строки.

Чего мне не хватает?Можно ли сделать то, что я хочу, в одной командной строке?

Ответы [ 3 ]

2 голосов
/ 05 апреля 2019

Следующая команда отвечает на ваш вопрос: она собирает все значения, содержащиеся в шаблоне Code>...<Code, если за ними следует шаблон Type>...<Type (с потенциально другими шаблонами между ними, но между ними нет других вхождений Code>...<Code между):

perl -lne 's/^.*?(?=Code>)//s; for (split /Code>/) { print qq($1:$2\n) if /(.*?)<Code.*?Type>(.*?)<Type/s }' -0777 <test.txt

Если, например, test.txt содержит следующие строки,

Code>test4<Code Type>false<Type
Code>test3<Code
Type>true<Type
Code>TEST1<Code Code2>best<Code2
Code>test2<Code
Type>false<Type

, то команда соберет следующие пары значений:

test4:false
test3:true
test2:false

Отредактировано 08/04/2019, 17:38 CEST Я отредактировал команду для удаления «части заголовка» файла (части до первого появления Code>),так как он может - по какой-то ошибке редактора файла - содержать закрывающий тег <Code, который был открыт не с Code>, а вместо этого с опечаткой, например, Cde>.Мое предположение состояло в том, что полный файл был «синтаксически правильным» в том смысле, что он состоит из элементов типа /(\w+)>.*?<\1/, разделенных пробелами (включая символы новой строки).Для файлов, которые не соответствуют этому синтаксису, заявление не было водонепроницаемым.

1 голос
/ 09 апреля 2019

Другой способ сделать это, используя прогрессивное сопоставление и встроенный код

perl -lne 'while (/\b(?:Code>(.*?)<Code(?{$c=$1})|Type>(.*?)<Type(?{print qq($c:$2\n) if defined $c;undef $c}))\b/g){}' -0777 <test.txt

Пояснения:

  • По сути, выражение находит вхождения Code>(.*?)<Code или Type>(.*)<Type.Это дает базовую форму чередования в неназванном групповом выражении: (?:Code>(.*?)<Code|Type>(.*?)<Type).
  • Утверждения границы слова \b вокруг группы обеспечивают совпадение ключевых слов Code и Type, но не, например, Code2 или TType.
  • Модификатор g обеспечивает последовательное применение регулярного выражения к строке.Поскольку я хочу извлечь результат внутри самого выражения, я помещаю регулярное выражение в пустой цикл, то есть while (/.../g) {}.
  • Вы предполагаете правило грамматики Code ⟶ Type, то есть вы ищете вхождения Type токен, следующий за Code токеном.Для этого токен Code запоминается в переменной $c с кодовым выражением (?{$c=$1}).Если обнаружен токен Type, он считается совпадающим только в том случае, если ранее был обнаружен токен Code, на что указывает тот факт, что определена переменная $c.В любом случае, если токен Type был найден, переменная $c будет undef d, чтобы подготовить его к следующему поиску.Это дает оценку кода (${print qq($c:$2\n) if defined $c;undef $c;}) в ветви Type регулярного выражения.
  • Обратите внимание, что перехваты токенов Code>(.*?)<Code и Type>(.*?)<Type могут быть пустой строкой.Вот почему я работаю с undef $c и if defined $c вместо простых $c='' и if $c.
0 голосов
/ 09 апреля 2019

если ваши данные в 'd', от gnu sed;

sed -Ez 's/.*Code>(\w+)<Code\sType>\w*<Type.*/\1/' d

Perl

perl -ne 'BEGIN{undef $/} /Code>(\w+)<Code\nType>\w*<Type/; print $1' d
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...