私はこれを調べていたのですが、理解できませんでした。
sed -n '1h; 1!H; ${ g; s/foo\nbar/bla\nblub/ p }' file.
catファイルは次の場所にあります:
foo
foo
bar
1!H
なぜそうなのかは1h
、パターンスペースを上書きしてしまい、1!H
役に立たないからです。
しかし、sed ワンライナーは正常に動作するようです。
答え1
見る@manatwork の回答実際の理由については1h;1!H
、移植性に関する注意事項を追加したいと思いました。
標準的で移植可能な構文は次のようになります。
sed -n '1h; 1!H; ${ g; s/foo\nbar/bla\
blub/p;}'
sed
そうしないと、従来の Unix 実装など、ほとんどの実装では動作しません。
\n
つまり、コマンドの左側では が理解されますがs
、右側ではバックスラッシュ文字の後に実際の改行文字を使用する必要があります。また、コマンドと;
の間にが必要であり、 の前にはスペースを入れないでください。s
}
p
ファイルの内容をホールド スペースではなくパターン スペースに保存することもできます。
sed -n '
:1
$!{
N;b1
}
s/foo\nbar/blah\
blup/p'
しかし、パターンとホールドスペースの両方について、ほとんどのsed
非 GNU 実装ではそれらのサイズが制限されているため、ほとんどの実装では小さなファイルでのみ機能します (POSIX では、8kiB のデータのみを保持できることが要求されています)。
ポータブルにするには、以下を使用する方がよいでしょうperl
:
perl -0777 -ne 'print if s/foo\nbar/blah\nblup/'
perl
ただし、 GNUではサイズに制限がないため、sed
プロセスごとのメモリ使用量に管理者が制限を設定していない場合は、システム メモリがすべて使用される可能性があり、システムのパフォーマンスに影響を及ぼす可能性があることに注意してください。
答え2
なぜ1!Hがあるかというと、1hはパターンスペースを上書きしてしまい、1!Hは役に立たないからです。
同じ入力行で実行されないため、上書きは発生しません。
1h # when input line number is 1, copy pattern space to hold space
1!H # when input line number is not 1, append pattern space to hold space
それは、次の理由により必要ですinfo sed
。
`H'
Append a newline to the contents of the hold space, and then
append the contents of the pattern space to that of the hold space.
したがって、H
すべての行を追加するために just を使用すると、最初の行の前に余分な改行が入ります。
bash-4.2$ seq 3 | sed -n 'H; ${g; p;}'
1
2
3
bash-4.2$ seq 3 | sed -n '1h; 1!H; ${g; p;}'
1
2
3