web-dev-qa-db-ja.com

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_analyzercontent_analyzer2、およびcontent_analyzer_itemsに続く引用符内のすべてを抽出する必要があります。

私はLinuxボックスでこれを行っているので、sed、Perl、grep、またはbashを使用したソリューションで問題ありません。

74
wrangler

結果にコンテンツを含めずにコンテンツを一致させる必要があるため(name="に一致する必要がありますが、目的の結果の一部ではありません)、ゼロ幅マッチングまたはグループキャプチャの何らかの形式が必要です。これは、次のツールを使用して簡単に実行できます。

Perl

Perlでは、nオプションを使用して、行ごとにループし、一致する場合はキャプチャグループの内容を出力できます。

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

GNU grep

GNU grepなどのgrepの改良版がある場合は、-Pオプションを使用できる場合があります。このオプションはPerlのような正規表現を有効にし、\Kを使用できるようにします。一致位置がリセットされるため、幅がゼロになる前のものはすべてリセットされます。

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

oオプションを使用すると、grepは行全体ではなく、一致したテキストのみを出力します。

Vim-テキストエディター

別の方法は、テキストエディターを直接使用することです。 Vimでは、これを実現するさまざまな方法の1つは、name=なしで行を削除し、結果の行からコンテンツを抽出することです。

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

標準grep

これらのツールにアクセスできない場合は、何らかの理由で、標準のgrepでも同様のことが実現できます。ただし、見回していない場合は、後でクリーンアップが必要になります。

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

結果の保存に関する注意

上記のすべてのコマンドで、結果はstdoutに送信されます。以下を追加してファイルにパイプすることでいつでも保存できることを覚えておくことが重要です。

> result

コマンドの最後まで。

137
sidyll

Perlを使用している場合、XMLを解析するモジュールをダウンロードします: XML :: SimpleXML :: Twig 、または XML :: LibXML =。車輪を再発明しないでください。

5
shawnhcorey

正規表現は次のようになります。

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

その後、グループ化は\ 1になります

5
Matt Shaver

この目的には、正規表現ではなくHTMLパーサーを使用する必要があります。 HTML::TreeBuilder を使用するPerlプログラム:

プログラム

#!/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
4

HTMLの整理と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
2
mitma

これはそれを行うことができます:

Perl -ne 'if(m/name="(.*?)"/){ print $1 . "\n"; }'
2
Benoit

もちろん、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
1
mitma

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 '"'
0
Carlos Lindado