この sed コマンドが実行するアクション: sed '1!G;h'

この sed コマンドが実行するアクション: sed '1!G;h'

私はsedをよりよく理解しようとしていますが、オンライン文書とマニュアルページを繰り返し閲覧したにもかかわらず、混乱しています。

私がそうするなら:(以内bash

echo "
alpha
beta
gamma" | sed '1!G;h'

わかります:

alpha
beta
alpha
gamma
beta
alpha

1!Gしたがって、ライン1を除く各入力ラインの後に新しいラインが追加されることがわかります。次に、hパターンスペースを予約済みスペースにコピーします。ただし、ホールドスペースでは何も起こらずにパターンスペースを出力する必要があります。この時点で、私は次のような1!G;h出力を見ることを期待しています1!G

alpha
beta

gamma

保持スペースは何とかエクスポートされますか?予約されたスペースが各ラインのパターンスペースの後に出力される場合、sed 'h'各ラインを2倍に増やすことはどうですか?

ああ、私はこれをmacOS Mojave 5で実行していますbash。どのバージョンを使用しているかはわかりませんが、sed最新のmacOSに付属しているデフォルトバージョンです。

答え1

G最初のコマンドは書きましたが、2番目のコマンドは作成した予約済みスペースに追加することを忘れました。

sed h各サイクルで予約されたスペースをカバーするので、各行を2倍にすることはありません。

最初のコマンドは次のとおりです。

sed '1!G;h' <<END_INPUT
alpha
beta
gamma
END_INPUT

そして出力

alpha
beta
alpha
gamma
beta
alpha

最初の行を除くすべての行に区切り線を使用して、現在予約されているスペースをパターンスペースに追加します。次に、ホールドスペースをパターンスペースで上書きします。各サイクルの終わり(入力ラインを処理した後)に暗黙的なp(印刷)コマンドがあります。

これを別の方法で表現すると、「各入力行に対して前の行をすべて逆順に出力します(最後に新しい行)」です。

だからコードは

  1. alphaパターンスペースで読む、alpha予約済みスペースにコピー、印刷alpha
  2. betaパターンスペースで読み取る、\nalpha予約済みスペースからパターンスペースとして追加、予約済みbeta\nalphaスペースにコピー、印刷beta\nalpha
  3. gammaパターンスペースを読み取り、\nbeta\nalpha予約済みスペースからパターンスペースとして追加し、gamma\nbeta\nalpha予約済みスペースにコピーして印刷しますgamma\nbeta\nalpha

パスワード

sed '1!G' <<END_INPUT
alpha
beta
gamma
END_INPUT

出力

alpha
beta

gamma

(3行目と最後行は空です。)

このsedコードは入力の各行を出力し、最初の行を除くすべての行に追加の改行を追加します。そうなるからこうするのだ

  1. alphaパターンスペースを読み、印刷しalpha
  2. betaパターンスペースを読み取り、\n予約済みスペースからパターンスペースとして追加して印刷しますbeta\n
  3. gammaパターンスペースを読み取り、\n予約済みスペースからパターンスペースに追加して印刷しますgamma\n

ここに予約済みスペースを追加すると、Gパターンスペースの末尾に追加の改行のみが追加されます。なぜなら、パターン空間は常に空であるからです(書き込みをしないので)。

答え2

私が試した結果:

]# echo  -e "a\nb\nc\nd\ne\nf" |sed '1!G;h' 
a
b
a
c
b
a
d
c
b
a
e
d
c
b
a
f
e
d
c
b
a

逆に読むと、「abcdef」、「abcde」、「abcd」、「abc」、「ab」、「a」になります。

それを何と呼びますか?

「G」が追加され、「h」が置き換えられているために機能します。これを省略すると、G;hブロック間に空白行が追加されます。


info sed「tac」の例があります。

sed -n '1!G;$p;h'

一度だけ印刷すると-n結果$pが完全に異なります。最後の「チャンク」です。sed '1!G;h'


Perlは(名前付き)変数を使用してこのアルゴリズムを簡単にエミュレートできます。

]# echo -e "a\nb\nc" | perl -ne '$hold = $_ . $hold; print $hold;'
a
b
a
c
b
a

着信行と保存された行のマージ方法を逆にします。

]# echo  -e "a\nb\nc" |perl -ne '$hold .= $_; print $hold;'
a
a
b
a
b
c

$_入力ラインです。 H=H+線、H=線+Hです。info sedこの内容と異なる微妙な点を見つけるには、注意深く読んでください。

答え3

もっと簡単なものから始めましょう。

$ seq 4 | sed 'G;h'
1

2
1

3
2
1

4
3
2
1

各ブロックは新しい数字を追加し、逆の順序で印刷します。
なぜこれが起こるのですか?このプロセスをゆっくり見てみましょう。

  1. 1sedはseq(a)の最初の数字(最初の行)を受け取ります。線はパターン空間に配置されます。
  2. 実行される最初のコマンドはであり、G改行文字を追加してからスペアスペース現在の配置スペースに移動します。最初に(ここでのように)予約されたスペースは空であるため、sedは改行文字と(スペース保存)空の文字列を現在のパターンスペースに追加します。簡単に言えば、入力の最初の行に改行文字を追加します。
  3. 2番目のコマンドはですh。パターンスペースを予約済みスペースにコピーします。予約済みスペースは1改行文字で構成されます。
  4. コマンドリストが終了したため、sedにはオプションがないため、sedはパターンスペース(aの1後に改行文字)を印刷します-n。その後、次の入力行に繰り返します。
  5. sed は 2 番目の行 a を取り、2パターン空間に配置します。
  6. 最初のコマンドはGです。したがって、sedはパターンスペースに追加されたスペース(1上記のaと改行、より短い形式で作成されます:)を予約します。1\nこれでパターンスペースが設定されました2\n1\n
  7. パターンスペースに含まれる内容が印刷されます。 sedは再ループします。
  8. 3行G\n2\n1\nには3
  9. このパターンスペースを3\n2\n1\n予約済みスペースにコピーするために使用されますh
  10. また、パターン空間は sed スクリプトの最後に印刷されます。
  11. 最後の行まで繰り返し、繰り返します。

上記の内容はすべて、行を逆順にキャプチャするのと同じです。

このスクリプトを使用すると、状況がより明確になる可能性があります(引用符で囲まれたスペースを使用l)。

$ seq 5 | sed -n 'G;h;l'
1\n$
2\n1\n$
3\n2\n1\n$
4\n3\n2\n1\n$
5\n4\n3\n2\n1\n$

そして、元のスクリプトは最初の行に改行文字を追加しません。

$ seq 5 | sed -n '1!G;h;l'
1$
2\n1$
3\n2\n1$
4\n3\n2\n1$
5\n4\n3\n2\n1$

今、アルファ、ベータ、ガンマを使用してください。

$ printf 'alpha\nbeta\ngamma' | sed -n '1!G;h;l'
alpha$
beta\nalpha$
gamma\nbeta\nalpha$

元のsedスクリプトに戻りましょう。

$ printf 'alpha\nbeta\ngamma' | sed '1!G;h'
alpha
beta
alpha
gamma
beta
alpha

実際、IMOは次のようになります。

$ printf 'alpha\nbeta\ngamma' | sed '1!G;h;$!d'
gamma
beta
alpha

すべての行が逆順になり、最後の繰り返しのみが印刷されます。

関連情報