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