awk 'NR==1{$4="ratio"}NR>1{$4 = ($3)/($2)} {print $1 "\t" $2 "\t" $3 "\t" $4}' A B
awk:コマンド。行:1:(FILENAME = A FNR = 18)致命的:0で除算しようとしました。
このエラーを解決するのに役立つ人がいますか?
NR==1
ここで合計はどういうNR>1
意味ですか?それは奇妙な例です。わかりません。 NRがレコード番号であることはわかりますが、ここではなぜ使用しますか?
答え1
作成者の例では、ファイルAとBを次の形式で想像しているようです。
ファイルA:
X Y Z
1 2 3
4 5 6
ファイルB:
6 7 8
o o 0
AWKの例では、4番目の列を生成します。ここで、NRは現在AWKによって処理されている行を表します。最初の行では、4番目の引数を文字列「ratio」(列名)に設定し、後続のすべての行では、4番目の引数を2番目の引数で割った3番目の引数に設定します。結果:
awk 'NR==1{$4="ratio"}NR>1{$4 = ($3)/($2)} {print $1 "\t" $2 "\t" $3 "\t" $4}' A
X Y Z ratio
1 2 3 1.5
4 5 6 1.2
6 7 8 1.14286
1 2 3 1.5
発生したエラーは次のとおりです。
awk:コマンド。行:1:(FILENAME = A FNR = 18)致命的:0で除算しようとしました。
ファイルAの18行目に2列と3列の数字が含まれていることを確認してください。
sedを使用して 'o'文字を0に変換できます。
cat A B | sed 's/\bo\b/0/g'
列 2 が 0 であることを確認し、それに応じてアクションを取ることができます。
awk 'NR==1{$4="ratio"}NR>1{if($2==0) $4 = "N/A"; else $4 = ($3)/($2)}
まとめると、次のような利点が得られます。
cat A B | sed 's/\bo\b/0/g' | awk 'NR==1{$4="ratio"}NR>1{if($2==0) $4 = "N/A"; else $4 = ($3)/($2)} {print $1 "\t" $2 "\t" $3 "\t" $4}'
X Y Z ratio
1 2 3 1.5
4 5 6 1.2
6 7 8 1.14286
0 0 0 N/A
答え2
与えられた例では、
awk 'NR==1{$4="ratio"}NR>1{$4 = ($3)/($2)} {print $1 "\t" $2 "\t" $3 "\t" $4}' A B
NR
これまでに読み込んだレコード数です。次の例では、これを使用して次のようにテーブルヘッダーをスキップできます。
Date Cost Quantity
2016/04/10 12.57 3
2016/04/19 11.74 2
なぜなら、「コスト」を「数量」(数字ではない)に分割できないからです。
ところで、あなたのデータできる4つ以上の列があります。ただし、awkを使用すると、入力データにない列に割り当てることができます。したがって、最初は$4="ratio"
既存の列を変更することも可能ですが、連続レコードの計算を反映するためにデータに列を追加する可能性があります。
エラー(0で割る)の解釈は別の質問ですNR
。数値データがあることを確認し、$2
パターン$3
を使用できます。たとえば、次の確認を追加します。
次のようなものを生産します
#!/bin/sh
awk 'function isnum(v) {
if ( v ~ /^[0-9.]+$/ )
return 1;
else
return 0;
}
(NR==1){$4="ratio"}
(NR>1 && NF >= 3 && isnum($2) && isnum($3) && $3 > 0){$4 = ($3)/($2)}
{print $1 "\t" $2 "\t" $3 "\t" $4}' A B
このisnum
関数は単純化されていますが、符号なしの素数を受け入れます。
1行のスクリプトを好む場合は、awkスクリプトが自由形式であることを覚えておいてください。だから...これを行うことができます:
awk 'function isnum(v){if(v~/^[0-9.]+$/)return 1;else return 0;}(NR==1){$4="ratio"}(NR>1&&NF>=3&&isnum($2)&&isnum($3)&&$3>0){$4=($3)/($2)}{print $1"\t"$2"\t"$3"\t"$4}' A B