
我將不勝感激你的幫助。我正在從數據文件中提取信息,這些文件在某些情況下大小超過 1 TB。
- 每行上的變數以空格分隔。
- 每個文件每行的變數數量是固定的
- 右三列始終為自然數
- 行總是以數組開頭
- 陣列始終包含每個檔案固定數量的元素
- 陣列可以包含 1 到 5 個元素
- 來源資料檔案已正確排序
下面的範例在使用並行時將三元素數組與檔案或區塊中的每個其他數組進行比較。如果陣列匹配,則新增右側第二列,並合併各行。最右邊的列和-2 列被刷新。
g@grml # zcat googlebooks-eng-us-all-3gram-20120701-zz.gz | head
Z'Z . _END_ 1840 1 1
Z'Z . _END_ 1847 1 1
Z'Z . _END_ 1850 1 1
Z'Z . _END_ 1855 1 1
Z'Z . _END_ 1856 1 1
Z'Z . _END_ 1857 1 1
Z'Z . _END_ 1860 1 1
Z'Z . _END_ 1863 1 1
Z'Z . _END_ 1865 1 1
Z'Z . _END_ 1869 1 1
g@grml # zcat googlebooks-eng-us-all-3gram-20120701-zz.gz | parallel -k -q --pipe awk '{a[$1" "$2" "$3] +=$(NF-1)} END{for (i in a) print i, a[i]}' | head
Zz_NOUN _NOUN_ , 98
zz _._ _PRT_ 120
ZZ or_CONJ _NOUN_ 122
ZZ_NOUN _DET_ _VERB_ 59
zz_DET _NOUN_ . 86
ZZ is_VERB reached 42
ZZ_NUM ^ ^ 65
ZZ _NOUN_ _VERB_ 3163
ZZ ,_. " 52
ZZ / _NUM_ 275
儘管該範例描述了一個 3 元素數組,但我正在處理包含 1 到 5 個元素的數組。
awk '{a[$1] +=$(NF-1)} END{for (i in a) print i, a[i]}'
awk '{a[$1" "$2] +=$(NF-1)} END{for (i in a) print i, a[i]}'
awk '{a[$1" "$2" "$3] +=$(NF-1)} END{for (i in a) print i, a[i]}'
awk '{a[$1" "$2" "$3" "$4] +=$(NF-1)} END{for (i in a) print i, a[i]}'
awk '{a[$1" "$2" "$3" "$3" "$5] +=$(NF-1)} END{for (i in a) print i, a[i]}'
如何告訴 awk 將當前數組與上一行的前一個數組進行比較,而不是讓 awk 嘗試將每個數組與文件或區塊中的每個數組進行匹配?
謝謝
範例來源檔案。
wget --show-progress -cq http://storage.googleapis.com/books/ngrams/books/googlebooks-eng-us-all-3gram-20120701-zz.gz -O - | zcat
答案1
註釋中作為 URL 給出的輸入資料以製表符分隔。這意味著我們可以將其第一個製表符分隔欄位解析為一種“鍵”,以便與其他行進行比較。我們的確是不是必須關心第一個欄位中的空格分隔的單字,但可以將整個第一個欄位視為單一實體。
BEGIN { OFS = FS = "\t" }
{
count = $(NF - 1)
key = $1
}
key != previous {
if (previous != "")
print previous, sum
sum = 0
}
{
sum += count
previous = key
}
END {
if (previous != "")
print previous, sum
}
程式awk
將“count”欄位(倒數第二個欄位)解析為count
,然後使用第一個欄位作為“鍵”,以便稍後與上一行的鍵進行比較。這是該區塊之後的第一個區塊BEGIN
(僅設定輸入和輸出分隔符號)。
如果該鍵與上一行的鍵不同,則表示我們現在正在查看其他一些單字集。輸出上一行的key和sum,並重置sum。
對於所有行,將總和增加該行的計數,然後更新previous
(我們現在已完成該行,因此該行是key
下一行的previous
)。
最後,輸出資料中最後一行的資訊。
您可以使用 來運行它awk -f script.awk inputfile
。
作為“一行”:
awk -F '\t' 'BEGIN{OFS=FS} {c=$(NF-1);k=$1} k!=p {if(p!="")print p,s;s=0} {s+=c;p=k} END {if(p!="") print p,s}' file