Как извлечь строку по шаблону с помощью GREP, REGEX или PERL



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



<table name="content_analyzer" primary-key="id">
<type="global" />
</table>
<table name="content_analyzer2" primary-key="id">
<type="global" />
</table>
<table name="content_analyzer_items" primary-key="id">
<type="global" />
</table>


Мне нужно извлечь что-нибудь в кавычках, которые следуют за "name=", т. е. content_analyzer , content_analyzer2 и content_analyzer_items.



Я делаю это на коробке Linux, поэтому решение с использованием sed, perl, grep или bash отлично.

845   8  

8 ответов:

так как вам нужно сопоставить контент, не включая его в результат (должен матч name=" но это не часть желаемого результата) некоторых форм требуется сопоставление нулевой ширины или захват группы. Это можно сделать легко с помощью следующих инструментов:

Perl

С Perl вы можете использовать n вариант для того чтобы закрепить петлей линию линией и напечатать содержимое группы захвата, если оно соответствует:

perl -ne 'print "\n" if /name="(.*?)"/' filename

GNU grep

если вы есть улучшенная версия grep, например GNU grep, у вас может быть элемент доступен. Этот параметр включает Perl-подобное регулярное выражение, позволяет использовать \K который является стенографическим взглядом. Он будет сброшен положение спички, поэтому что-нибудь перед ним нулевая ширина.

grep -Po 'name="\K.*?(?=")' filename

The o опция заставляет grep печатать только совпадающий текст, а не вся линия.

Vim-Текстовый Редактор

другой способ-использовать текстовый редактор непосредственно. С Vim, одним из различными способами достижения этого было бы удаление строк без name= а затем извлечь содержимое из полученных строк:

:v/name=/d
:%s/\v.*name\="([^"]+)".*/

стандартный grep

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

grep -o 'name="[^"]*"' filename

примечание о сохранении результаты

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

> result

до конца команды.

регулярное выражение будет:

.+name="([^"]+)"

тогда группировка будет в \1

Если вы используете Perl, загрузите модуль для анализа XML: XML:: Simple,XML:: Twig или XML:: LibXML. Не изобретайте заново колесо.

для этой цели следует использовать парсер HTML, а не регулярные выражения. Программа Perl, которая использует HTML::TreeBuilder:

программа

#!/usr/bin/env perl

use strict;
use warnings;

use HTML::TreeBuilder;

my $tree = HTML::TreeBuilder->new_from_file( \*DATA );
my @elements = $tree->look_down(
    sub { defined $_[0]->attr('name') }
);

for (@elements) {
    print $_->attr('name'), "\n";
}

__DATA__
<table name="content_analyzer" primary-key="id">
  <type="global" />
</table>
<table name="content_analyzer2" primary-key="id">
  <type="global" />
</table>
<table name="content_analyzer_items" primary-key="id">
  <type="global" />
</table>

выход

content_analyzer
content_analyzer2
content_analyzer_items

это может сделать это:

perl -ne 'if(m/name="(.*?)"/){ print  . "\n"; }'

вот решение с использованием HTML tidy & xmlstarlet:

htmlstr='
<table name="content_analyzer" primary-key="id">
<type="global" />
</table>
<table name="content_analyzer2" primary-key="id">
<type="global" />
</table>
<table name="content_analyzer_items" primary-key="id">
<type="global" />
</table>
'

echo "$htmlstr" | tidy -q -c -wrap 0 -numeric -asxml -utf8 --merge-divs yes --merge-spans yes 2>/dev/null |
sed '/type="global"/d' |
xmlstarlet sel -N x="http://www.w3.org/1999/xhtml" -T -t -m "//x:table" -v '@name' -n

ой, команда sed должна предшествовать аккуратной команде, конечно:

echo "$htmlstr" | 
sed '/type="global"/d' |
tidy -q -c -wrap 0 -numeric -asxml -utf8 --merge-divs yes --merge-spans yes 2>/dev/null |
xmlstarlet sel -N x="http://www.w3.org/1999/xhtml" -T -t -m "//x:table" -v '@name' -n

если структура вашего xml (или текста в целом) фиксирована, самый простой способ-использовать cut. Для вашего конкретного случая:

echo '<table name="content_analyzer" primary-key="id">
  <type="global" />
</table>
<table name="content_analyzer2" primary-key="id">
  <type="global" />
</table>
<table name="content_analyzer_items" primary-key="id">
  <type="global" />
</table>' | grep name= | cut -f2 -d '"'

Comments

    Ничего не найдено.