Как я могу несколько раз совпадать с A до B в VIM? - PullRequest
0 голосов
/ 10 апреля 2009

Мне нужно получить весь текст между <Annotation> и </Annotation>, где встречается слово MATCH. Как я могу сделать это в VIM?

<Annotation about="MATCH UNTIL </Annotation>   " timestamp="0x000463e92263dd4a" href="     5raS5maS90ZWh0YXZha29rb2VsbWEvbGFza2FyaS8QyrqPk5L9mAI">                                                                        
  <Label name="las" />
  <Label name="_cse_6sbbohxmd_c" />
  <AdditionalData attribute="original_url" value="MATCH UNTIL </Annotation>       " />
</Annotation>
<Annotation about="NO MATCH" href="     Cjl3aWtpLmhlbHNpbmtpLmZpL2Rpc3BsYXkvbWF0aHN0YXRLdXJzc2l0L0thaWtraStrdXJzc2l0LyoQh_HGoJH9mAI">
  <Label name="_cse_6sbbohxmd_c" />
  <Label name="courses" />
  <Label name="kurssit" />
  <AdditionalData attribute="original_url" value="NO MATCH" />
</Annotation>
<Annotation about="MATCH UNTIL </ANNOTATION>     " score="1" timestamp="0x000463e90f8eed5c" href="CiZtYXRoc3RhdC5oZWx     zaW5raS5maS90ZWh0YXZha29rb2VsbWEvKhDc2rv8kP2YAg">
  <Label name="_cse_6sbbohxmd_c" />
  <Label name="exercises_without_solutions" />
  <Label name="tehtäväkokoelma" />
  <AdditionalData attribute="original_url" value="MATCH UNTIL </ANNOTATION>" />
</Annotation>

Ответы [ 2 ]

4 голосов
/ 10 апреля 2009

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

Узор:

\(<Annotation\(\s*\w\+="[^"]\{-}"\s\{-}\)*>\)\@<=\(\(<\/Annotation\)\@!\_.\)\{-}"MATCH\_.\{-}\(<\/Annotation>\)\@=

Давайте разберемся с этим ...

Группа 1 - <Annotation\(\s*\w\+="[^"]\{-}"\s\{-}\)*>. Соответствует начальному тегу элемента Attribute. Группа 2, которая встроена в Группу 1, соответствует атрибуту и ​​может повторяться 0 или более раз.

Группа 2 - \s*\w\+="[^"]\{-}"\s\{-}. Большинство из этих частей обычно используются; наиболее необычным является \{-}, что означает не жадное повторение (*? в Perl-совместимых регулярных выражениях). Нежадное совпадение пробелов в конце важно для производительности; без него Vim попытается всеми возможными способами разделить пробелы между атрибутами между \s* в конце группы 2 и \s* в начале следующего вхождения группы 2.

За Группой 1 следует \@<=. Это позитивный взгляд нулевой ширины. Он предотвращает включение начального тега в сопоставляемый текст (например, для s ///).

Группа 3 - \(<\/Annotation\)\@!\_.. Он включает в себя группу 4, которая соответствует началу конечного тега атрибута. \@! является отрицательным прогнозом нулевой ширины, а \_. соответствует любому символу (включая символы новой строки). Вместе эти группы соответствуют любому символу, кроме того, где начинается конечный тег атрибута. За Группой 3 следует жадный маркер повторения \{-}, чтобы он соответствовал наименьшему блоку текста перед МАТЧ. Если бы вы использовали \_. вместо группы 3, сопоставляемый текст мог бы включать конечный тег элемента Annotation, который включал not , включая MATCH и продолжался до следующего элемента Annotation с MATCH. (Попробуйте.)

Следующий бит прост: найдите MATCH и минимальное количество других символов перед конечным тегом.

Группа 5 проста: это конечный тег. \@= является положительным прогнозом нулевой ширины, который включен сюда по той же причине, что и \@<= для начального тега. Мы должны повторить <\/Attribute вместо использования \4, потому что группы с модификаторами нулевой ширины не фиксируются.

3 голосов
/ 10 апреля 2009

Должно ли быть выполнено в vim? Не могли бы вы обмануть и открыть второе окно, в котором вы помещаете что-то в большее / меньшее, в котором указано, на какой номер строки перейти в vim?

- редактировать -

Я никогда не выполнял многострочного поиска / поиска в vi [m]. Однако, чтобы обмануть в другом окне:

perl -n -e 'if ( /<tag/ .. /<\/tag/)' -e '{ print "$.:$_"; }' file.xml | less

покажет элементы / блоки для «тега» (или других длинных совпадающих имен) с номерами строк в меньшем количестве, и затем вы сможете искать другой текст в каждом блоке.

Достаточно близко?

- редактировать -

в пределах "меньше", введите

/MATCH

для поиска совпадений. На левом поле будет номер строки, где находится этот экземпляр (в пределах целевого элемента / тегов).

в пределах vi [м], введите

:n

где "n" - номер нужной строки.

Конечно, если то, что вы действительно хотели сделать, это что-то вроде поиска / восстановления / замены, это более сложно. На этом этапе awk / perl / ruby ​​(или что-то похожее, что соответствует вашим вкусам ... или xsl?) Действительно инструмент, который вы должны использовать для преобразования.

...