
私はこのファイルを持っています:
sometext1{
string1
}
sometext2{
string2
string3
}
sometext3{
string4
string5
string6
}
このファイルから特定の文字列を検索し、その文字列より前のすべての項目を最初から印刷し、{
その文字列の後のすべての項目を最後まで印刷したいと思います}
。これを達成するためにsedを使用してみましたが、範囲内のすべての内容を印刷しようとすると、たとえば/{/,/string2/
sedは次のように印刷します。
sometext1{
string1
}
sometext2{
string2
sometext3{
string4
string5
string6
}
文字列「string2」を検索すると、次のような出力が必要です。
sometext2{
string2
string3
}
ありがとうございます。
答え1
これには2つのコマンドがあります。.*{$
シーケンスの最後の行まで切り捨てるコマンドが必要な場合(@don_crisstiがそうであるようにed
)あなたはできます:
sed 'H;/{$/h;/^}/x;/{\n.*PATTERN/!d'
...これは、ewline文字H
の後の前のスペースに各行を追加し\n
、h
一致する各行の前のスペースを上書きし、{$
一致する各行の前のh
スペースとパターンスペースを置き換え^}
てバッファをフラッシュする方法で機能します。
これはewline{
に一致する行のみを印刷し、\n
特定PATTERN
のポイントから印刷します。これはバッファスワップの直後にのみ発生します。
{$
シーケンスの最後の一致まで、一連の一致からすべての行を削除しますが、含まれているすべての行を取得できます。たとえば、次のようになります。
sed '/PATTERN.*\n/p;//g;/{$/,/^}/H;//x;D'
それがすることは、h
各シーケンスのパターンと前の空白を置き換え...{$.*^}.*
、シーケンスのすべての行を前の行文字のH
後の前のスペースに追加し\n
、各行を繰り返してパターンスペースに最初に現れるewline文字をD
削除することです。\n
その後、残りのコンテンツから始めてください。
もちろん、\n
パターン空間でewlineを取得する唯一の時間は、入力行が一致する場合^}
(範囲の終わり)であるため、他の場合にスクリプトを再実行すると、通常どおり次の入力行が取得されます。
ただし、PATTERN
ewlineと同じパターンスペースにある場合は、\n
バッチを上書きする前に印刷してください。^}
(範囲を終了してバッファをフラッシュできるように)。
この入力ファイルが与えられると(お金ありがとうございます):
sometext1{
string1
}
sometext2{
PATTERN
string3
}
sometext3{
string4
string5
string6
}
Header{
sometext4{
some string
string unknown
here's PATTERN and PATTERN again
and PATTERN too
another string here
}
}
最初のものは次のように印刷されます。
sometext2{
PATTERN
string3
}
sometext4{
some string
string unknown
here's PATTERN and PATTERN again
and PATTERN too
another string here
}
...そして2番目の...
sometext2{
PATTERN
string3
}
Header{
sometext4{
some string
string unknown
here's PATTERN and PATTERN again
and PATTERN too
another string here
}
答え2
解決策は次のとおりですed
。
ed -s filename <<< $'g/PATTERN/?{?,/}/p\nq\n'
それは:
g/PATTERN/ # mark each line matching PATTERN
?{?,/}/p # for each marked line, print all lines from the previous { up to the next }
q # quit editor
PATTERN
これは、各ペアの間に1つの行しかないと仮定します。それ以外の場合は、同じブロック内の追加の行ごと{
}
に冗長出力が得られます。これは、2つの異なるセクションを含むテストファイルなど、1行の一致を含む複数のファイルで機能します。PATTERN
{
}
PATTERN
PATTERN
sometext1{
string1
}
sometext2{
PATTERN
string3
}
sometext3{
string4
string5
string6
}
Header{
sometext4{
some string
string unknown
here's PATTERN again
another string here
}
}
走る
ed -s sample <<< $'g/PATTERN/?{?,/}/p\nq\n'
出力:
sometext2{
PATTERN
string3
}
sometext4{
some string
string unknown
here's PATTERN again
another string here
}
答え3
そしてpcregrep
:
pcregrep -M '(?s)\{[^}]*PATTERN.*?\}'
または、grep
入力にNULバイトが含まれていない場合は、GNUを使用してください。
grep -Poz '.*(?s)\{[^}]*PATTERN.*?\}'
答え4
$ awk 'BEGIN{RS="\n\n"; FS="[{}]"} {if ($2 ~ /string4/) {print $2}}' t1.txt
string4
string5
string6
どこ:
string4
-->一致させる文字列t1.txt
-->クエリに記載されているファイルの内容が含まれています。