sed正規表現は、パターンを含む段落全体をキャプチャできません。

sed正規表現は、パターンを含む段落全体をキャプチャできません。

このXMLファイルがあります(例)。

<This is a line of text with a year=2020 month=12 in it
This line of text does not have a year or month in it
This year=2021 is the current year the current month=1
This is the year=2021 the month=2/>


<This is a line of text with a year=33020 month=12 in it
This line of text does not have a year or month in it
This year=33020 is the current year the current month=1
This is the year=33020 the month=2/>

私のLinuxディストリビューション(sed(GNU sed)4.2.2)に付属のインストールを使用して、次の正規sed表現を使用してこのファイルを検索します。

 sed -En 'N;s/\<(This.*2020.*[\s\S\n]*?)\>/\1/gp' test2.txt

ただし、次の文字列のみをキャプチャします。

<This is a line of text with a year=2020 month=12 in it
This line of text does not have a year or month in it

しかし、まずは全体を捉えようとします。パターン間<と埋め込み。>

私がここで何を間違っているのか?

ベストアンサー1

これが期待どおりに機能しない理由は、正規表現<>エスケープする必要がなく、特別な意味がないからです。しかし、\<そして\> するGNU拡張正規表現(有効化を含む-E)には特別な意味があります。つまり、単語の境界で一致します。単語の\<始まりと終わりを一致させます。\>したがって、\<(This実際には一致しませんが、<単語の先頭に一致しますThis\>最後のものも同じだ。 GNUsedマニュアルには一例これはほぼ正確にあなたが追求するものです:

$ sed -En '/./{H;1h;$!d} ; x; s/(<This.*2020.*?>)/\1/p;' file
<This is a line of text with a year=2020 month=12 in it
This line of text does not have a year or month in it
This year=2021 is the current year the current month=1
This is the year=2021 the month=2/>

sedこの種の作業には特に適していないと思います。私は以下を使用しますperl

$ perl -000 -ne 'chomp;/<.*2020.*?>/s && print "$_\n"; exit' file
<This is a line of text with a year=2020 month=12 in it
This line of text does not have a year or month in it
This year=2021 is the current year the current month=1
This is the year=2021 the month=2/>

ここでは、「短絡モード」()でPerlを使用しています。-000これは、「行」が2つの連続した\n文字(つまり空白行)として定義されることを意味します。このスクリプトは次のことを行います。

  • chomp:「行」(段落)の末尾にある末尾の改行を削除します。
  • /<.*2020.*?>/s && print "$_\n":この「行」(段落)が<0個以上の文字、20200個以上の文字、0個以上の文字と一致する場合、>改行文字(print "$_\n")が追加されて印刷されます。s一致演算子の修飾子は.改行文字の一致を許可します。

別のオプションは次のとおりですawk

$ awk 'BEGIN{RS="\n\n"} /<.*2020.+?>/' file
<This is a line of text with a year=2020 month=12 in it
This line of text does not have a year or month in it
This year=2021 is the current year the current month=1
This is the year=2021 the month=2/>

レコード区切り文字をRS2つの連続した改行に設定し、上記と同じ正規表現を使用して一致させます。一致が見つかった場合(または他のジョブがtrueを返すとき)、デフォルトの動作は現在のレコードを印刷するため、awk必要な内容が印刷されます。

おすすめ記事