awk すべての行を列ごとに別の行に分割します。

awk すべての行を列ごとに別の行に分割します。

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変数の型を確認できますか?

おすすめ記事