可変数の列を持つパイプで区切られたファイルを解析し、欠落している列を置き換えて固定数の列に変換する

可変数の列を持つパイプで区切られたファイルを解析し、欠落している列を置き換えて固定数の列に変換する

|各行には、可変数の列/フィールドがあるパイプで区切られたファイルがあります。最初の 2 つのフィールドと最後の 2 つのフィールドのみが常に存在し、間には最大 10 個までの多様な (偶数) フィールド数があるため、行には合計最大 14 個のフィールドがあります (2 + 0 .. .10 + 2)。

目的は、「不足している」フィールドを置き換え、ファイルを行ごとに固定数の列を持つファイルに変換することです。

C_A「変数」フィールドの特徴は、常に...形式の「インデックスキー」C_Eと値で構成されることです。

入力例:

10|100|C_A|val_18|C_D|val_20|50|60
40|200|C_A|val_5|C_B|val_10|C_C|val_30|C_D|val_90|C_E|val_83|40|45
80|100|C_E|val_90|50|60

予想される結果は次のとおりです。

10|100|C_A|val_18|||||C_D|val_20|||50|60
40|200|C_A|val_5|C_B|val_10|C_C|val_30|C_D|val_90|C_E|val_83|40|45
80|100|||||||||C_E|val_90|50|60

ベストアンサー1

GNU awk名前をフィールドインデックスにマッピングすることでこの問題を解決できます。

  • C_A => $3
  • C_B => $5 ...など。
$ awk '
  BEGIN {
    OFS = FS = "|"
    n = split("A-B-C-D-E", x, "-")
    for (i=1; i<=n; ++i) h["C_" x[i]] = 2*(i-1) + 3
  }
  {
    # record which out of
    # ca/cb/.../ce present
    for (i=3; i<NF-2; i+=2) seen[$i] = $(i+1)

    # store fields in preparation
    # for re-filling them based on seen
    nf = split($0, f, FS); $0=""

    # fill up the first two..easy does it
    $(1) = f[1]
    $(2) = f[2]

    # recall which fields c_? 
    # were seen then fill up
    # corresponding field and field value 
    for (var in h) {
      i = h[var]
      if (var in seen) {
        $(i) = var
        $(i+1) = seen[var]
      } else { $(i) = $(i+1) = ""}
    }

    # append the last two fields
    $(NF+1) = f[nf-1]
    $(NF+1) = f[nf]
    # above line **NOT** a typo

    # clear out the array seen
    # for the next iteration
    split("", seen, ".")
  }1
' file

結果:

10|100|C_A|val_18|||||C_D|val_20|||50|60
40|200|C_A|val_5|C_B|val_10|C_C|val_30|C_D|val_90|C_E|val_83|40|45
80|100|||||||||C_E|val_90|50|60

おすすめ記事