file1.txtのすべての行をfile2.txtの単一行の対応する(列別)値に分割しようとしています。
猫ファイル1.txt
1 2.5 3
7 7 7
1 3 5
猫ファイル2.txt
1 3 5
この問題の提案された解決策に従ってください。https://stackoverflow.com/questions/44908195/awk-multiplication-of-all-rows-in-a-table-with-first-row-of-the-table、次のコードを思い出しました。
cat file2.txt file1.txt | awk 'NR==1{split($0,m);CONVFMT="%.5f\t";next} {for (i=1;i<=NF;i++) $i=$i/m[i]} 1'
しかし、行の1つのすべての値が1で、CONVFMTが整数で機能しないため、出力ファイルの形式はめちゃくちゃです。この問題を解決するために、CONVFMTの代わりにタブ区切り文字を持つprintfを使用することを検討していますが、実際のファイルに可変数の列があることを考慮すると、$ 1、$ 2などを使用してハードコーディングされたソリューションは望ましくありません。私はawkに精通していないので、解決策を自分で理解することはできません。
助けてくれてありがとう!
編集:出力のすべての数字は%.5f形式でなければなりません。
答え1
すべてのフィールドをにフォーマットするには、次のものを%.5f
使用できますsprintf
。
BEGIN {
OFS = "\t"
}
NR == 1 {
cols = split($0,m)
next
}
NF == cols {
for (i=1; i<=NF; i++)
$i = sprintf("%.5f", $i/m[i])
}
1
$ awk -f above.awk file2 file1
1.00000 0.83333 0.60000
7.00000 2.33333 1.40000
1.00000 1.00000 1.00000
上記awk
のプログラムは、発生する可能性のあるエラーについて警告しません。あなたは試すことができます:
NR == 1 {
cols = split($0,m)
for (i in m)
if (m[i] == 0)
err("field "i" is "m[i]"; division by zero is fatal", 1)
next
}
NF != cols {
err("found "NF" fields, expected "cols)
next
}
{
for (i in m)
$i = sprintf("%.5f", $i/m[i])
print
}
END {
exit errs
}
function err(msg, r) {
# Print message to stderr
# Leave non-zero exit status
# Optionally go to END
printf "%s - %s.\n", "error: line "FNR" in "FILENAME, msg | "cat >&2"
errs = 1
if (r) exit
}
また、各フィールドが数値であることを確認したい場合があります。awkが数値でない場合はエラーを生成します。;awk変数の型を確認できますか?
答え2
残念ながら、必要な出力形式に関する質問は明確ではありません。
ただし、一般的に「表形式の出力」を保証するために、結果を次にパイピングしてみることができますcolumn
。
awk 'BEGIN{CONVFMT="%.5f"} FNR==NR{split($0,div);next} NR>FNR{for (i=1;i<=NF;i++) $i=$i/div[i];}1' file2.txt file1.txt | column -t
これにより
1 0.83333 0.60000
7 2.33333 1.40000
1 1 1
提供された入力例の場合。
ちなみに、ファイル操作時には(またはなど)cat
を使用する必要はありません。awk
sed
修正する
編集内容を見ると、すべての数字が5桁の小数点浮動小数点として表示されることがわかります。この場合、@guestの解決策は正しいアプローチですが、column
後で列見出しを印刷したい場合でもまだ役に立ちます。