最初の行、3番目の行、5番目の行のすべてのフィールドで、次のデータセットの終わりまで、値3と4をそれぞれ0と1に置き換えたいと思います。
2 4 3 0
2 4 3 0
3 0 4 4
3 0 4 4
4 2 4 3
4 2 4 3
2 3 4 2
2 3 4 2
したがって、望ましい結果は次のとおりです。
2 1 0 0
2 4 3 0
0 0 1 1
3 0 4 4
1 2 1 0
4 2 4 3
2 0 1 2
2 3 4 2
そのために次のコードを使用しています。
awk '{for (i = 1; i <= NR; i=(i+2))
if($i == 3) {$i = 0}
if($i == 4) {$i = 1}
}
END {print $0}' b.temp
ただし、このコードの出力は、b.tempファイルの最後の行(2 3 4 2)の値のみです。
どうやってやるの?コードは、任意の数の行とフィールドに対してそれを行う必要があります。ソリューションは、シェルスクリプトでawk、sed、またはその他の方法で作成できます。
前もって感謝します
Sedを使用:
sed 'y/34/01/;n' file
つまり:
ただし、データにたとえば14が含まれている場合は、11に変換すると失敗します。これを回避するには、
sed 's/\<4\>/1/g;s/\<3\>/0/g;n' file
このアプローチの問題は、print
ブロックにEND
ステートメントが1つしかないことです。そのブロックの$0
の値は、ファイルの最終行の内容です。したがって、awk
コードはファイルの最後の行のみを出力します。
また、{ ... }
ブロックの前に条件がない場合(awk
がファイルの終わりにのみ適用されるなど)を除き、END
は操作をevery lineに適用することに注意してください。したがって、コードは1、3などをチェックしようとしますフィールドすべての行であり、それが3
または4
である場合、それぞれ0
または1
で置き換えます...しかし、決して結果を印刷します。
すべての奇数行にルールを適用するために、NR%2
が1(または単にゼロ以外)かどうかを確認できます。
awk 'NR%2{for (i=1;i<=NF;i++) if ($i==3 || $i==4) $i-=3}1' b.temp
1
は、ルールの外で発生する場合、「実行されたすべての変換から得られた行を出力する」ためのawk
省略表記です。
より最適化されたコマンドは以下にあります私の試みです
コマンド
awk 'NR==1||NR==3||NR==5||NR==7{gsub("3","0",$0)}1' file | awk 'NR==1||NR==3||NR==5||NR==7{gsub("4","1",$0)}1'
出力
2 1 0 0
2 4 3 0
0 0 1 1
3 0 4 4
1 2 1 0
4 2 4 3
2 0 1 2
2 3 4 2