タイトルに基づいてアイテムを配置する方法は? [閉鎖]

タイトルに基づいてアイテムを配置する方法は? [閉鎖]

次のように、スペースで区切られた5000行以上の行があります。

Item_A: Acou#1  Bla#5

Item_B: Acou#1  Elfa#2  Flq#2

Item_C: Acou#1  Bla#4   Elfa#2  Flq#2

Item_D: Agly#3  Bla#4   Elfa#2

以下のように、テーブルのすべての内容と数量の共通ヘッダーを持つテーブルを作成したいと思います。

             Acou  Agly  Bla  Elfa  Flq

Item_A:      1     0     5    0     0

Item_B:      1     0     0    2     2

Item_C:      1     0     4    2     2

Item_D:      0     3     4    2     0

私は「Acou」、「Bla」などを含む行を探しました。次に、Excelで編集して数量化し、個々のファイルをすべて1つのファイルにまとめます。しかし、時間がかかりました。

ベストアンサー1

BEGIN { OFS = "\t" }

# Collect headers from data
FNR == NR {
    for (i = 2; i <= NF; ++i)
        if (!($i in heads))
            heads[$i]
    next
}

# Output header
FNR == 1 {
    line = "Items"
    for (j in heads)
        line = line OFS j
    print line
}

{
    line = $1
    # Iterate through the header items, testing each field against it
    for (j in heads) {
        found = 0 # assume not found
        for (i = 2; !found && i <= NF; ++i)
            if ($i == j)
                found = 1 # matches header
        line = line OFS found
    }
    print line
}

データに対して次のコマンドを実行します(空行を削除した後)。

$ awk -f script.awk file file
Items   Acou#1  Bla#4   Bla#5   Elfa#2  Agly#3  Flq#2
Item_A: 1       0       1       0       0       0
Item_B: 1       0       0       1       0       1
Item_C: 1       1       0       1       0       1
Item_D: 0       1       0       1       1       0

入力データファイルを2回指定する必要があります。二度スキャンしたからです。最初のスキャンでは、FNR == NR各行(ブロック)のデータ項目が収集されます。 2番目のスキャンでは、収集された各データ項目(ヘッダー)を各データ行に対してテストします。

出力は、単に0ヘッダーのフィールドが行のデータにあるかどうかと存在する1場合です。これはないかなり何を求めるのか、だから…

タイトルを切り取り、#結果部分を#表示するデータとして使用するバリアントです。

BEGIN { OFS = "\t" }

# Collect headers from data
FNR == NR {
    for (i = 2; i <= NF; ++i) {
        split($i, h, "#")
        if (!(h[1] in heads))
            heads[h[1]]
    }
    next
}

# Output header
FNR == 1 {
    line = "Items"
    for (j in heads)
        line = line OFS j
    print line
}

{
    line = $1
    # Iterate through the header items, testing each field against it
    for (j in heads) {
        found = 0 # assume not found
        for (i = 2; !found && i <= NF; ++i) {
            split($i, h, "#")
            if (h[1] == j)
                found = h[2] # matches header
        }
        line = line OFS found
    }
    print line
}

実行してください:

$ awk -f script.awk file file
Items   Elfa    Bla     Acou    Agly    Flq
Item_A: 0       5       1       0       0
Item_B: 2       0       1       0       2
Item_C: 2       4       1       0       2
Item_D: 2       4       0       3       0

列の順序は必ずしもソートされません(関連付け配列のキーとして格納されるため)。私はそれを読者が分類できるように練習として残します。

おすすめ記事