最初の列の内容をループ構造に置き換えます。

最初の列の内容をループ構造に置き換えます。

変更したい最初の列を持つファイルがあります。たとえば、次のファイルがあります(元のファイルには複数の列がありましたが、次の列は2列に切り捨てられ、ファイルの末尾に空白行がある可能性があります)。 )。

テスト.txt:

0 a
2 b  
3 c 
4 d
5 e


最初の列の内容を0 - > 2、2 - > 3、3 - > 5、4 - > 0、5 - > 4に変更する必要があります。最終ファイルは次のとおりです。

2 a
3 b
5 c
0 d
4 e


私は次のようにawkを使ってみました。

awk '$1=="0"{$1="2"} $1=="2"{$1="3"} $1=="3"{$1="5"} $1=="4"{$1="0"} $1=="5"{$1="4"};1' test.txt

しかし、awkは1行ずつ読み取らず、必要なものを変更しないので、出力は次のようになります。

4 a
4 b
4 c
0 d
4 e


私が必要なPython、sed、awk、または他のスクリプトツールに変換するのに役立つ人は誰でも歓迎します。

ベストアンサー1

AWKは実際に1行ずつ読みます。next各割り当て後に印刷後にステートメントを追加すると、残りのコードはスキップされます。

awk '$1=="0"{ $1="2"; print; next }
     $1=="2"{ $1="3"; print; next }
     $1=="3"{ $1="5"; print; next }
     $1=="4"{ $1="0"; print; next }
     $1=="5"{ $1="4"; print; next }1' infile

または、代わりに制御フラグを使用してください。

awk '!s && $1=="0"{ $1="2"; s=1 }
     !s && $1=="2"{ $1="3"; s=1 }
     !s && $1=="3"{ $1="5"; s=1 }
     !s && $1=="4"{ $1="0"; s=1 }
     !s && $1=="5"{ $1="4"; s=1 }
                  { print; s=0  }' infile

ただし、次のようにすべての操作を実行できます。

awk -F'( )' 'BEGIN{ split("2 1 3 5 0 4", map) }
$1!=""{ $1=($1+1 in map)?map[$1+1]:$1 }1' infile

そして分割(文字列、arryName)関数map以下のようにインデックスと値の名前付き配列を作成し、配列はFSに基づいて分割されます(デフォルトはSpace / Tabs)。

Index        Value
map[<0>+1] -->   2
map[<1>+1] -->   we choice it 1 so it will be unchanged for <1> --> 1
map[<2>+1] -->   3
map[<3>+1] -->   5
map[<4>+1] -->   0
map[<5>+1] -->   4

<#>角度内の数字は最初の列の値であり、awkでは、配列のインデックス付けはゼロではなく1から始まり、列の値を1ずつ増やし、マップされた配列からその値を取得します。


一般的な解決策として(ただし、ほとんどのカスタムキー/値は連続的であり、配列インデックスをキーとして使用できるため、上記のソリューションを引き続き使用します)、そうでない場合は、次のことができます。

awk -F'( )' 'BEGIN{ len=split("0 2 2 3 3 5 4 0 5 4", map) }
{ for(i=1; i<=len/2; i+=2 ) if($1==map[i]){ $1=map[i+1]; break} }1' infile

おすすめ記事