プログラムでフィールド区切り文字(FS)を変更し、gawkで現在のレコードを再計算しますか?

プログラムでフィールド区切り文字(FS)を変更し、gawkで現在のレコードを再計算しますか?

特定のレコードのフィールド区切り記号()のみを変更し、FS新しいフィールド区切り文字を使用してレコード($0)、フィールド($N)、およびフィールド数()を再計算しようとしています。NFしかし、これはうまくいかないようです。

例:これには、スペースで区切られた3つのフィールドとして解釈される行があります。フィールド区切り文字をに変更してnレコード($1 = $1)を強制的に書き換えると、次の印刷に示すようにレコードは変更されていません$1

$ echo 'one two three' | awk '1 {FS="n" ; OFS=":" ; $1 = $1 ; print $1}'
> one

しかし、私は出力が次のようになりたいと思います。

> o

走りながら記録の再構成を強制するコツは$1 = $1以下のとおりです。友達マニュアル。だから私はそれがうまくいくことを願っています。何が問題なのかよく分からない。

FSOFS単純に設定してから通常のレコードを期待するprintか、print $0変更されたレコードを印刷してレコードのフィールド区切り文字を変更しようとするのは一般的な間違いです。

ただし、レコード自体を変更するために何も実行されないため、これは機能しません。代わりに、通常は$1 = $1[...]のような方法でレコードを強制的に書き換える必要があります。

(私はGNU Awk 5.2.2を使用しています)

答え1

~について

特定のレコードのフィールド区切り文字(FS)のみを変更したいと思います。

split()そのレコードを使用すると、コードがよりクリーンでシンプルになります。

$ 0を書き換えて$ 0を再分割するという2つの概念を混同しています。

$0 再構築:フィールドに値を変更または割り当てると、$ 0がフィールドに書き換えられ、各FSがOFSに置き換えられます。

$ echo 'one two three' |
    awk '{FS="n" ; OFS=":" ; $1 = $1 ; print; for (i=1; i<=NF; i++) print i, $i}'
one:two:three
1:one
2:two
3:three

$0 再割り当て:$ 0に値を変更または割り当てると(フィールドの変更により再構築された結果を除く)、$ 0は既存のFS値を使用してフィールドに再分割されます。

$ echo 'one two three' |
    awk '{FS="n" ; OFS=":" ; $0 = $0 ; print; for (i=1; i<=NF; i++) print i, $i}'
one two three
1:o
2:e two three

次に、次の結果を理解し、上記の説明を理解したことを確認してください。

再構築してから再分割します。

$ echo 'one two three' |
    awk '{FS="n" ; OFS=":" ; $1 = $1 ; $0 = $0; print; for (i=1; i<=NF; i++) print i, $i}'
one:two:three
1:o
2:e:two:three

パーティションを分割して再構築してください。

$ echo 'one two three' |
    awk '{FS="n" ; OFS=":" ; $0 = $0; $1 = $1 ; print; for (i=1; i<=NF; i++) print i, $i}'
o:e two three
1:o
2:e two three

答え2

引用したテキストを見てみましょう。

最後に、awksumフィールドの現在の値を使用してレコード全体を強制的に書き換えるのが便利な場合がありますOFS

後で次のようになります。

$0ドメインとの関係には別の側面があります。すべての割り当ての$0ため、レコードは次のようにフィールドに再解析されます。現在のの価値FS

前の文では言及せずにFS2番目の文で強調した場合、予想される方法は次のとおりです。$0 = $0反対側ではレコードが変更されます。出力フィールドの値が何であれ、解析を試みずに次のことを行います。

% echo 'one two three' | awk '1 {FS="n" ; OFS=":" ; $0 = $0 ; print $1}'
o

% echo 'one two three' | awk '{FS="n" ; OFS=":" ; $1 = $1 ; print}'
one:two:three

私はGNU awkを使用しません。

% awk --version
awk version 20200816

しかし、私はGNU awkも同じことができたらと思います。

関連情報