行を列に変換する方法

行を列に変換する方法

行値を列値に変換するのに役立ちます。私の入力はfile.dat次のとおりです

最初の2つのフィールドはそれぞれアルファベット文字列と数字です。入力には常に同じ数のフィールドがあります。6

入力する

A|1|DLT|07:30|10:30|34
A|1|STG|07:30|10:30|NA
A|1|MAIN|06:30|10:30|NA
A|2|STG|07:30|10:30|NA
A|2|UNLD|04:30|10:30|90
B|1|DLT|03:30|10:30|34
B|1|STG|07:30|09:30|NA
B|1|MAIN|07:25|10:30|NA
B|1|UNLD|05:30|12:30|8

出力に変化があります。出力フィールドすべての行には18個のフィールドがあり、各行には入力ファイルの最初の2つのフィールドがあり、その後には次の順序で3番目、...、18番目のフィールドがあります。ここで、空のフィールドは入力ファイルから欠落している行です。レコードの順序はDLTで、STG、MAIN、およびUNLDの後に対応するレコードが続きます。

出力

A|1|DLT|07:30|10:30|34|STG|07:30|10:30|NA|MAIN|06:30|10:30|NA|||| 
A|2|||||STG|07:30|10:30|NA|||||UNLD|04:30|10:30|90
B|1|DLT|03:30|10:30|34|STG|07:30|09:30|NA|MAIN|07:25|10:30|NA|UNLD|05:30|12:30|8
  • A | 1 UNLDがありません
  • A | 2にはDLTとMAINはありません。
  • 記録は失われません。

同様に、入力ファイルの3番目のフィールドに対応するレコードが見つからない場合は、出力フィールドが次のようになるように空の値に置き換える必要があります。18地域

答え1

私のawkアドバイス:

awk -F'|' '{ if (a[$1$2] == "") {
               a[$1$2] = $0
             } 
             else {
               a[$1$2] = a[$1$2]","$3"|"$4"|"$5"|"$6
             }
           }
           END {
             for (key in a) {
               print a[key]
             }
           }' <input.txt | sort

説明する

この-F'|'オプションは定義しますフィールド区切り記号awk行のフィールドを解析するために使用されます)はファイル形式なので、文字「|」として使用されます。

a[...]配列です。配列はawkインデックスではなく、Python辞書に多少似ています。これは実際に文字列です。入力ファイルの各行のテストでは、エントリが存在する場合は最初の2つのフィールド(最初の行など)if (a[$1$2] == "")に対応するキーを確認します。$1$2 = A1そうでない場合(A|1|...最初の行を読み取る)、行全体がこのキー(a[$1$2] = $0)に保存されます。すでにコンテンツがある場合(A|1|...別の行が保存されている場合)、エントリをコンマで連結し、「|」を使用してフィールドを3から6まで区切ります。 (a[$1$2] = a[$1$2]","$3"|"$4"|"$5"|"$6)。

最後に、ファイルの検索が完了したら、各キーのエントリを出力する必要があります。私たちはENDこれをブロックで行います(このコマンドはすべてのファイルを読み取った後に実行されます)。これを行うには、for (key in a)配列()のすべてのキーを繰り返し、各キーの項目を印刷します。

その後、最終出力はにパイプされますsort。配列キーは英数字で巡回されないため、後で行などをawk取得できるように出力をソートする方がきれいになります。A|1|...A|2|...


最後の編集により、すべてが少しトリッキーになりました。必要な指示がawk多少複雑になる可能性があるため、スクリプトファイルを生成することをお勧めします(例:拡張子付きのテキストファイルの生成awk)。次のスクリプトをコピーしてください。.awkmyScript.awk

BEGIN { FS="|" }

$3 == "DLT" {
  dlt[$1"|"$2]=$3"|"$4"|"$5"|"$6
  a[$1"|"$2]++
}

$3 == "STG" {
  stg[$1"|"$2]=$3"|"$4"|"$5"|"$6
  a[$1"|"$2]++
}

$3 == "MAIN" {
  main[$1"|"$2]=$3"|"$4"|"$5"|"$6
  a[$1"|"$2]++
}

$3 == "UNLD" {
  unld[$1"|"$2]=$3"|"$4"|"$5"|"$6
  a[$1"|"$2]++
}

END {
  for (key in a) {
    if (dlt[key] == "") dlt[key]="|||"
    if (stg[key] == "") stg[key]="|||"
    if (main[key] == "") main[key]="|||"
    if (unld[key] == "") unld[key]="|||"
    print key"|"dlt[key]"|"stg[key]"|"main[key]"|"unld[key]          
  }
}

それを書く:

awk -f myScript.awk <input.txt | sort

私の元の答えの説明を理解したら、このアルゴリズムも理解できます。今回は、各データ型(dlt、stg、main、unld)の配列を作成し、その値を最初の2つのフィールドに対応するキーに保存します。配列はaすべての可能なキーを追跡するために使用されます。最後に、配列のキーを繰り返しa、そのキーのデータ配列の1つが空の場合は、必要に応じて "|||"を入力し、各行に18のフィールドがあります。

答え2

少し違うバレンタインB.の回答:

awk -F"|" '
     {
        key = $1 "|" $2
        a[key] = 1
        b[key][$3] = $3 "|" $4 "|" $5 "|" $6
     }
 END {
        subtype[1] = "DLT"
        subtype[2] = "STG"
        subtype[3] = "MAIN"
        subtype[4] = "UNLD"
        for (key in a)
            {
                output = key
                for (i = 1; i <= 4; i++)
                    {
                        st = subtype[i]
                        if (b[key][st] == "")
                                output = output "||||"
                        else
                                output = output "|" b[key][st]
                    }
                print output
            }
     }' file.dat

のようにバレンタインB.の回答:

  • -F"|"|入力行からフィールドを抽出できるように、フィールド区切り記号をに設定します。
  • keyA|1または、A|2またはB|1 通常、最初の2つのフィールドの接続に設定します。これを使用して、そのキーの組み合わせに関連するデータの最大4行を結合します。
  • a[key]表示するデータ(キー)を記録するには1に設定します。
  • b[key][$3]キーの後ろの残りの行に設定します。たとえば、にb["A|1"]["DLT"]設定されます"DLT|07:30|10:30|34"。このように、我々はログを残すことができます。みんな私たちが見るデータ(質問で指定されているように行に6つ以下のフィールドがあると仮定)に何が含まれているのかわからず、これを行うことに注意してください$3

すべてのデータを読んだ後:

  • サブタイプ(たとえば、有効な値、「DLT」、「STG」、「MAIN」、および「UNLD」)を定義する配列な$3ので、サブタイプを複数回リストする必要はありません。
  • 私たちが見たすべてのキーを繰り返します。出力ラインの構築を開始します。
  • 上記の4つのサブタイプを繰り返します。そのキーとそのサブタイプのデータがある場合はそれを出力行に追加し、そうでない場合は4つの空のフィールドを追加します。
  • この行を印刷してください。

sort出力を整列させるには、パイプで接続します。 (私が「もし」と言った理由は、たとえ質問がプログラム出力例はソートされていますが、これが出力をソートする必要があるわけではありません。 )

2番目のフィールドに何があるかについての質問は正確ではありません。ただ「数字」としか出ていません。数値が異なる整数になり、数値でソートするには、次のようにします。

sort -t"|" -k1,1 -k2,2n

答え3

4番目のフィールドの値をキャプチャし、「val」という変数に保存します。

配列を作成し、最初と2番目のフィールドに基づいて配列の値を追加します。

最後に、配列値を印刷して小さな調整(交換、削除など)を行います。

$ awk -F\| '{ val=$3;
              for (i=4;i<=NF;i++) {val=val"|"$i}
              Arr[$1OFS$2]=Arr[$1OFS$2]","val;
              next
            }
        END { for (i in Arr) {
                  A=Arr[i];
                  sub(" ","|",i);
                  print i,A
              }
            }' test.txt | sed "s/ ,/\|/"
A|1|DLT|07:30|10:30|34 ,STG|07:30|10:30|NA ,MAIN|06:30|10:30|NA
B|1|DLT|03:30|10:30|34 ,STG|07:30|09:30|NA ,MAIN|07:25|10:30|NA ,UNLD|05:30|12:30|8
A|2|UNLD|04:30|10:30|90 ,DLT|08:30|11:30|4 ,STG|07:30|10:30|NA

関連情報