2

以下は、列 12 のデータに対してうまく機能しますが、すべて同じではない 70 を超える列があり、すべての列を出力する必要があり、変換された列は科学的値を置き換えます。

 awk -F',' '{printf "%.41f\n", $12}' $file

ありがとう

これで一行..

2012-07-01T21:59:50,2012-07-01T21:59:00,1817,22901,264,283,549,1,2012-06-24T13:20:00,2.600000000000000e+001,4.152327506554059e+001,-7.893523806678388e+001,5.447572631835938e+002,2.093000000000000e+003,5.295000000000000e+003,1,194733,1.647400093078613e+001,31047680,1152540,29895140,4738,1.586914062500000e+000,-1.150000000000000e+002,0.000000000000000e+000,0.000000000000000e+000,0.000000000000000e+000,0.000000000000000e+000,0.000000000000000e+000,0.000000000000000e+000,0.000000000000000e+000,3.606000000000000e+003,0.000000000000000e+000,0.000000000000000e+000,0.000000000000000e+000,4.557073364257813e+002,0.000000000000000e+000,0.000000000000000e+000,0.000000000000000e+000,11,0.000000000000000e+000,2.000000000000000e+000,0,0,0,0,4.466836981009692e-004,0.000000000000000e+000,0.000000000000000e+000,0.000000000000000e+000,8,0,840,1,600,1,6,1,1,1,5,2,2,2,1,1,1,1,4854347,0,-

アップデート

これは、変換されていない出力に対して機能しています。何らかの理由で、else if ステートメントを挿入するのに少し問題があります。ファイルまたはcliですべての構文エラーが発生するようです。

awk -F',' '{for (i=1;i<=NF;i++) {if (i <= 9||i == 16||i == 17||i == 19||i == 20||i == 21||i == 22|| i == 40|| i == 43||i == 44||i == 45||i == 46||i >= 51) printf ($i",")};}' $file

上記のコードに次のステートメントを挿入しますか??

else if (i == 10) printf ("%.41f", $i)

解決した

うまくいきました。素晴らしいアイデアをありがとう。awk -f を使用してファイルで機能させることはできないようですが、コマンドラインではこれはうまく機能しています。この1つのライナーをプログラムに入れました。

awk -F',' '{for (i=1;i<=NF;i++) {if (i <= 9||i == 16||i == 17||i >= 19&&i <= 22|| i == 40|| i >= 43&&i <= 46||i >= 51&&i <= 70) printf($i","); else if (i == 10||i == 18) printf("%.2f,", $i); else if (i == 11||i == 12) printf("%.41f,", $i); else if (i == 13) printf("%.1f,", $i); else if (i == 14||i == 15||i >= 24&&i <= 46) printf ("%d,", $i); else if (i == 23) printf("%.4f,", $i); else if (i >= 47&&i <= 50) printf("%.6f,", $i); if (i == 71) printf ($i"\n")};}'

結果

2012-07-01T21:59:50,2012-07-01T21:59:00,1817,22901,264,283,549,1,2012-06-24T13:20:00,26.00,41.52327506554058800247730687260627746582031,-78.93523806678388154978165403008460998535156,544.8,2093,5295,1,194733,16.47,31047680,1152540,29895140,4738,1.5869,-115,0,0,0,0,0,0,0,3606,0,0,0,455,0,0,0,11,0,2,0,0,0,0,0.000447,0.000000,0.000000,0.000000,8,0,840,1,600,1,6,1,1,1,5,2,2,2,1,1,1,1,4854347,0,-
4

2 に答える 2

3

AWK では数値も文字列であるため、ループ内で正規表現マッチングを実行して各フィールドの形式を選択できます。

#!/usr/bin/awk -f
BEGIN {
    d = "[[:digit:]]"
    OFS = FS = ","
}
{
    delim = ""
    for (i = 1; i <= NF; i++) {
        if ($i ~ d "e+" d d d "$") {
            printf "%s%.41f", delim, $i
        }
        else {
            printf "%s%s", delim, $i
        }
        delim = OFS
    }
    printf "\n"
}

編集:

上記のバージョンを変更したので、ファイル内で AWK スクリプトとしてどのように使用されるかがわかります。それを保存し (「scinote」と呼びます)、executable として設定するとchmod u+x scinote、次のように実行できます。./scinote inputfile

また、質問に追加した最新バージョンを少し簡単にするために修正したので、上記のようにスクリプト ファイルに入れる準備ができました。

#!/usr/bin/awk -f
BEGIN {
    plainlist = "16 17 19 20 21 22 40 43 44 45 46"
    split(plainlist, arr)
    for (i in arr) {
        plainfmt[arr[i]] = "%s"
    }
    OFS = FS = ","
}
{
    delim = ""
    for (i = 1; i <= NF; i++) {
        printf "%s", delim
        if (i <= 9 || i in plainfmt || i >= 51) {
            printf plainfmt[i], $i
        }
        else if (i == 10) {
            printf "%.41f", $i
        }
        else if (i == 12) {
            printf "%.12f", $i
        }
        delim = OFS
    }
    printf "\n"
}

他の形式のフィールドが (1 つだけではなく) ある場合は、plainfmt配列と同様のことができます。

于 2012-07-07T19:28:55.473 に答える
0

いつでもすべてのデータ フィールドをループして、printf. 仕組みをテストするためだけの単純なファイルの場合、これを試すことができます:

 awk '{for (i=1; i<=NF; i++) printf("%d = %s\n", i, $i);}' data.txt

ここで-Fは設定されていないため、フィールドは空白で分割されることに注意してください。

NFは、1 行のフィールド数の定義済み変数です。フィールドは 1 から始まります (例: $1$2など$NF)。$0全行です。

あなたの例では、これはうまくいくかもしれません:

  awk -F',' '{for (i=1; i<=NF; i++) printf "%.41f\n", $i}' $file

以下のコメントに基づいて更新します(システムで構文をテストするのではありません):

特定のフィールドを異なる方法で処理する必要がある場合は、switchステートメントまたはif ステートメントを使用して、異なるフィールドを異なる方法で処理する必要がある場合があります。スクリプトをファイルに保存すると、これは簡単になります。それso.awkを呼び出して、次のように呼び出しましょう。

  awk -f so.awk $file

スクリプトには、次の行に沿って何かが含まれている場合があります。

BEGIN{ FS=',' }
{ for (i=1; i<=NF; i++)
    {
      if (i == 20 || i == 22|| i == 30)
        printf( " .. ", $i)
      else if ( i == 13 || i == 24)
        printf( " ....", $i)
      etc.
    }
}

もちろん、if (i > 2) ...または他の範囲を使用して、可能であればすべてのフィールドをリストする必要をなくすこともできます。

この一連の if ステートメントの代替として、上記の switch ステートメントを参照してください。

于 2012-07-07T17:33:56.077 に答える