2つのgrepを1つのコマンドに結合

2つのgrepを1つのコマンドに結合

次のXMLがあります。

    <artifactId>myproject</artifactId>
    <version>1.14.0-SNAPSHOT</version>

バージョンを抽出したいです1.14.0-SNAPSHOT。つまり、2つのgrepとパイプを使用してこれを行う方法を知っています。

$ grep -A1 "<artifactId>myproject</artifactId>" pom.xml | grep -Eo "\d+.\d+.\d+-SNAPSHOT"

2つを1つにまとめるにはどうすればよいですか?これにawkまたはsedを使用する方が良いでしょうか?

答え1

<version>次の行以降に確実であればmyproject

sed -n '
    \|<artifactId>myproject</artifactId>|{
        n                                           #get next line
        s|[[:blank:]]*</\?version>[[:blank:]]*||gp  #remove tags and print
    }
' pom.xml

またはあなたが持っているなら正規表現

grep -zoP '<artifactId>myproject</artifactId>\s*\n\s*<version>\K[^<]+' pom.xml

答え2

あなたはコメントで移植可能なものが欲しいと言いました。本当に素晴らしいことですが、そうしないように心からアドバイスします。XML状況に合った言語ですが、正規表現はそうではありません。正規表現はXML結果を正しく解析しません。

せいぜい、XMLが同じ形式で保持されている場合にのみ機能するハックを取得できます。しかし、XML仕様によれば、形式は偶然であり、同じ意味を維持することができます。これは危険な仮定であり、脆弱なコードを引き起こす可能性があります。

私はあなたがこれをしたい理由があることを知っています。あなたはすでに方法を提供する答えを持っています。私はパーサーがまだ正しい答え。

ただし、XMLパーサーを使用すると、xpath正規表現に非常に似ていますが、階層的な情報を取得できます。

このような:

#!/usr/bin/env perl
use strict;
use warnings;

use XML::Twig;

my $twig = XML::Twig -> parse ( \*DATA );

my $version = $twig -> get_xpath('//item/artifactId[string()="myproject"]/../version',0)->text;
print $version;

__DATA__
<xml>
  <item>
    <artifactId>myproject</artifactId>
    <version>1.14.0-SNAPSHOT</version>
  </item>
</xml>

xpathどのように機能するかを見ることができます。//item構造内のどこでもアイテムを探します。[string()=テキストの内容を照会します。[@someAtt="fish"]プロパティの確認などの操作を実行できます。

次に、..上に(item)上がってversion要素を取得します。次にtext値を取得します。

個人旅行者として:

perl -MXML::Twig -0777 -e 'print XML::Twig -> parse ( <> ) -> get_xpath('/item/artifactId[string()="myproject"]/../version',0)->text,"\n"    yourxmlfile.xml

今はXML::Twig学習しやすいと思ってお勧めします。XML::LibXMLかなり良いです。

ただし、WindowsではStrawberry Perlと一緒に展開され、多くのパッケージマネージャまたはで簡単に使用できますCPAN

または -xmlstarletあなたも同じことをすることを許可する必要があります。

関連情報