1. ホーム
  2. regex

[解決済み] grep, regex, perlでパターンに沿った文字列を抽出する方法 [重複].

2022-11-17 22:32:06

質問

こんな感じのファイルがあります。

    <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_analyzer2content_analyzer_items .

私はLinuxボックスでこれをやっているので、sed、perl、grepまたはbashを使用した解決策で結構です。

どのように解決するのですか?

コンテンツは結果に含めずにマッチさせる必要があるため(must マッチ name=" にマッチしなければならないが、それは目的の結果の一部ではない) ので、何らかの形で ゼロ幅マッチングまたはグループキャプチャが必要です。 これは以下のツールで簡単に行うことができます。 以下のツールで簡単にできます。

Perl

Perlでは n オプションを使って、一行ずつループさせ キャプチャグループにマッチした場合、その内容を表示します。

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

GNU グレップ

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 で同様のことが実現できます。しかし、ルックアラウンドなしで を使用すると、後でいくつかのクリーンアップが必要になります。

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


結果の保存に関する注意事項

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

> result

をコマンドの末尾に追加します。