awkをストリームエディタとして使用する

awkをストリームエディタとして使用する

awkテキスト操作のスイス軍用ナイフです。ただし、本文の小さな部分を変更しなければならない場合にはsed全体的な修正を加えます。おそらく作業に最適なツールかもしれませんが、これらの簡単なタスクを実行するために他のツールを使用する方法を知ることも価値があります。awkフローエディタを置き換えてどのように使用しますかsed

特に次のファイルを使用してくださいtext

Comparing apples with oranges.
Comparing rockets with bicycles.

次の結果を取得する方法awk:

sed 's/apples/fruit/' text
sed 's/apples\|oranges/fruit/g' text

awkボーナスとして、この関数を使用して変数をどのように変更できますか?

ベストアンサー1

ストリームエディタは特別なタイプのフィルタです。フィルタは、標準入力からテキストを取得していくつかの魔法を実行し、それを標準出力に印刷するプログラムです。 grep、基本的にすべてのcoreutilsフィルタ。ストリームエディタは特別なタイプのフィルタです。着信テキストに1つ以上の編集コマンドを適用します。

では、awk次の3つの機能を使用できます。息子格子要約は次のとおりです。

sub(regexp, replacement [, target])
gsub(regexp, replacement [, target])
gensub(regexp, replacement, how [, target])

3つの関数をすべてtarget省略すると、$0現在の行()が想定されます。

サブとgsub

まず見てみましょうsub

$ awk '{rt = sub(/apple|orange/, "fruit"); print rt, $0}' text 
1 Comparing fruits with oranges.
0 Comparing rockets with bicycles.

ここで関数の戻り値はsub()に保存されますrt/apple|orange/一致appleまたはorange適用を意味する正規表現一度。呼び出し後は何も起こりませんがsub、そのあとでは現在行が変更され、戻り値に値があります。

戻り値は0何の変化もない値です。つまり、subを外部に適用すると{action}シミュレーションに使用できるという意味ですsed

$ awk 'sub(/apple|orange/, "fruit")' text    
Comparing fruits with oranges.

これで最初の行だけが変更されたので、最初の行だけが印刷されます。指定しない場合は、その行を印刷する操作が実行されることに注意してください。

シミュレーションするには、sed 's/apple/fruit/' text次のように書くことができます。

$ awk 'sub(/apple|orange/, "fruit") || 1' text
Comparing fruits with oranges.
Comparing rockets with bicycles.

これで最初の機能が試行されます。何かが置き換えられると、ゼロ以外の値が返され、その行が印刷されます。何も置き換えられない場合は、PATTERN2回目のテストが試みられます。これは常にゼロではありません。つまり、1。その結果、(未修正)行が印刷されます。

同じで、おそらくより慣用的に書くもう一つの方法は次のとおりです。

$ awk '{sub(/apple|orange/, "fruit")};1' text 
Comparing fruits with oranges.
Comparing rockets with bicycles.

ここでは、最初のブロックACTIONの現在の行を変更してみます。戻りコードはsub自動的に無視されます。何も印刷されません。 2番目PATTERN{ACTION}- ブロック(1)、常にマッチ、idf topの基本的な作業は、変更された行か変更されていない行に関係なく印刷することです。

最初の行の2番目の項目は置き換えられていないことを確認しましたorange。 1つの解決策は、sub-functionをwhileループにラップすることです。

$ awk '{while (sub(/apple|orange/, "fruit")){}};1' text
Comparing fruits with fruits.
Comparing rockets with bicycles.

subは、ゼロ以外の値が返される限りsub繰り返されます。これを便利に短縮し、whileループがaで機能しないため、関数が導入されましたPATTERNgsub

$ awk 'gsub(/apple|orange/, "fruit")' text             
Comparing fruits with fruits.

これはsed 's/regex/replacement/g'、有名なものが次のように模倣できることを意味します。awk

awk '{gsub(/apple|orange/, "fruit")};1' text

gensub: 副作用なし

警告するgensubPOSIX awk規格に準拠しておらず、インストール時に使用できない可能性があります。gawkでは使用できますが、ではbusybox awk使用mawkできませんnawk

これらのメカニズムは、すでに変数操作がどのように機能するかを示しています。変数はその場で変更されます。

$ awk '{a=$0; rt=sub(/apple|orange/, "fruit", a); print rt, a, $0}' text
1 Comparing fruits with oranges. Comparing apples with oranges.
0 Comparing rockets with bicycles. Comparing rockets with bicycles.

これはあなたが望むものではないかもしれません。コンピューティングの健全な原則は、入力自体を処理するのではなく、入力のコピーを処理することです。入力を変更したくありませんが、代替結果を新しい変数に割り当てるとどうなりますか?入力するgensub

$ awk '{rt=gensub(/apple|orange/, "fruit", "g"); print rt, $0}' text
Comparing fruits with fruits. Comparing apples with oranges.
Comparing rockets with bicycles. Comparing rockets with bicycles.

ここで戻り値は戻り値ではありませんが、結果の文字列が変数rtに割り当てられます。 4番目のパラメータのデフォルト値は$ 0です。

gensubの3番目の引数はメソッドです。このパラメータの適切な値は「g」または「G」で、これはグローバルを表します。これにより、/regex/のすべての項目が代替文字列に変更されます。 i番目の項目が置き換えられる正の整数iを指定することもできます。

$ gawk '{print gensub(/apple|orange/, "fruit", 1)}' text
Comparing fruits with oranges.
Comparing rockets with bicycles.

$ gawk '{print gensub(/apple|orange/, "fruit", 2)}' text
Comparing apples with fruits.
Comparing rockets with bicycles.

$ gawk '{print gensub(/apple|orange/, "fruit", 3)}' text
Comparing apples with oranges.
Comparing rockets with bicycles.

$ gawk '{print gensub(/apple|orange/, "fruit", "g")}' text
Comparing fruits with fruits.
Comparing rockets with bicycles.

gawk は、正の整数、G または g で始まる文字列でない場合に警告を出します。

gensubの別の慣用的な使用法は、代替結果を直接印刷することです。最後の形式はsed 's/regex/replacement/g'コマンドを置き換えることもできます。

交換用のストリングでより多くの作業を行う

これまで、私たちは直接文字列置換を行いました。一致する文字列を変更するにはどうすればよいですか?

一致するテキストをキャプチャする特別な変数があります。 POSIX準拠のsubとgsubを使用すると、&を使用して一致する部分を繰り返すことができます。

$ awk '{rt=gsub(/apple|orange/, "a basket of &"); print rt, $0}' text
2 Comparing a basket of apples with a basket of oranges.
0 Comparing rockets with bicycles.

sed と perl/PCRE の数値マッチングに関連する奇妙な点は、sub と gsub の変形に比べて現代的すぎる。 gensubは&と同じ操作を実行できますが、正規表現を指定するために正規表現でグループ化を使用すると、より多くの操作を実行できます。

$ awk '{rt=gensub(/(appl|orang)(e)/, "a basket of \\1\\2","g"); print rt}' text
Comparing a basket of apples with a basket of oranges.
Comparing rockets with bicycles.

TL;DR

迅速で汚れた作業には、subとgsubを使用してください。

  • 変数を直ちに変更したいと前の値に気にしない場合
  • 戻りコードを使用して交換するかどうかに応じてアクションを実行する場合

gensub他のすべての場合には、次を使用します。

  • 代替文字列のより詳細な逆参照を提供します。
  • 元の変数を変更せずに保持したい場合
  • 結果を変数に割り当てたい場合

おすすめ記事