次のように、スペースで区切られた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
列の順序は必ずしもソートされません(関連付け配列のキーとして格納されるため)。私はそれを読者が分類できるように練習として残します。