2016-03-02 68 views
0

我不是很瞭解Linux,而且我有一個非常大的文本文件(幾個Gig),我希望找到最常見的單詞(比如前50)以及每個單詞出現次數,並有這些數字輸出到一個文本文件,像這樣:使用Awk輸入大文本文件並輸出最常見的單詞文本文件?

2500 and 

我怎麼可以這樣用awk? (它並不是特別需要使用Awk,但是我在Windows 7上使用Cygwin,我不確定還有什麼其他的東西可以用來做這種事情)。

我已經採取了看看這個問題: https://unix.stackexchange.com/questions/41479/find-n-most-frequent-words-in-a-file

雖然如前所述我不是太熟悉Linux和管道等,並希望如果有人能解釋每個命令的作用。

+0

'tr'將字母數字字符的補碼('-c')翻譯爲換行符。 'sort'將單詞帶到一起,然後'uniq -c'爲每個帶有計數的不同單詞生成一行。 'sort -nr'然後按照數字排序計數,從最大到最小,'head -10'給出前10行。在Unix變體中,包括Linux和Cygwin,'man'命令(用於手冊)給出了每個命令的參考。因此,'man tr'會給出'tr'的手冊頁,等等。 – mpez0

回答

0

我通過複製整個文件創建了一個文件article 。這awk一個班輪可能是一個開始。

awk -v RS="[:punct:]" '{for(i=1;i<=NF;i++) words[$i]++;}END{for (i in words) print words[i]" "i}' file

出海賊王:

1 exploration 
1 day 
1 staggering 
1 these 
2 into 
1 Africans 
4 across 
5 The 
1 head 
1 parasitic 
1 parasitized 
1 discovered 
1 To 
1 both 
1 what 
1 As 
1 inject 
1 hypodermic 
1 succumbing 
1 glass 
1 picked 
1 Observatory 
1 actually 

的完整版本。我使用兩個文件,一個使用英語停用詞,另一個使用包含我們想要提取最常用詞(50)的詞的文件。

BEGIN { 
    FS="[[:punct:] ]"; 
} 
FNR==NR{ 
    stop_words[$1]++; 
    next; 
} 
{ 
    for(i=1;i<=NF;i++) 
    { 
     if (stop_words[$i]) 
     { 
      continue; 
     } 

     if ($i ~ /[[:alpha:]]+/)# add only if de value is alphabetical 
     { 
      words[$i]++; 
     } 
    } 
} 
END { 
    PROCINFO["sorted_in"] = "@val_num_desc" 
    for (w in words) 
    { 
     count++; 
     print words[w], w; 
     if (count == 50) 
     { 
      break; 
     } 
    } 
} 

如何運行它。 awk -f script.awk english_stop_words.txt big_file.txt

+0

感謝這看起來像是在正確的軌道上,是否可以限制顯示多少結果來表示50?並以降序顯示結果(基於頻率)? – hjalpmig

+0

@hjalpmig我認爲這是可能的,但它必須是一個awk腳本,而不是一個班輪。讓我花點時間思考一下。 – Firefly

+0

您可能希望在FS中使用POSIX字符類'[:punct:]',而不是識別某些特定的標點符號。你目前缺少'!','''等等。 –

0

這裏是一個Python版本:

from collections import Counter 

wc=Counter() 

with open('tale.txt') as f: 
    for line in f: 
     wc.update(line.split()) 

print wc.most_common(50) 

運行上Tale of Two Cities產量:

[('the', 7514), ('and', 4745), ('of', 4066), ('to', 3458), ('a', 2825), ('in', 2447), ('his', 1911), ('was', 1673), ('that', 1663), ('I', 1446), ('he', 1388), ('with', 1288), ('had', 1263), ('it', 1173), ('as', 1016), ('at', 978), ('you', 895), ('for', 868), ('on', 820), ('her', 818), ('not', 748), ('is', 713), ('have', 703), ('be', 701), ('were', 633), ('Mr.', 602), ('The', 587), ('said', 570), ('my', 568), ('by', 547), ('him', 525), ('from', 505), ('this', 465), ('all', 459), ('they', 446), ('no', 423), ('so', 420), ('or', 418), ('been', 415), ('"I', 400), ('but', 387), ('which', 375), ('He', 363), ('when', 354), ('an', 337), ('one', 334), ('out', 333), ('who', 331), ('if', 327), ('would', 327)] 

您也可以拿出來與awksorthead模塊化/ Unix的類型的解決方案:

$ awk '{for (i=1;i<=NF; i++){words[$i]++}}END{for (w in words) print words[w]"\t"w}' tale.txt | sort -n -r | head -n 50 
7514 the 
4745 and 
4066 of 
3458 to 
2825 a 
2447 in 
... 

無論語言,配方是一樣的:

  1. 創建字的associative array及其頻率計數
  2. 逐行讀取文件中的行,並通過文字
  3. 排序添加到關聯數組字數組頻率並打印所需數量的條目。

你還需要考慮一個'單詞'是什麼。在這種情況下,我簡單地將空間用作非空間塊之間的分隔符作爲「單詞」。這意味着Andand + "And都是不同的單詞。分隔標點符號是通常涉及正則表達式的附加步驟。

+0

謝謝,我設法讓你的Python腳本的編輯版本工作(不得不改變一些字符編碼的東西,並將其改爲逐行打印)。如果可能的話,我也想得到一個Awk版本的工作,但已經很晚了,所以我會盡量做到這一點,並明天挑選並回答,歡呼尋求幫助! – hjalpmig

1

這一切都取決於你的一個「字」的定義,但如果我們假設它是不區分大小寫字母字符的連續序列,然後用GNU AWK(這是你的cygwin獲得AWK)一個辦法是:

awk -v RS='[[:alpha:]]+' ' 
    RT { cnt[tolower(RT)]++ } 
    END { 
     PROCINFO["sorted_in"] = "@val_num_desc" 
     for (word in cnt) { 
      print cnt[word], word 
      if (++c == 50) { 
       exit 
      } 
     } 
    } 
' file 

當@dawgs' Tale of Two Cities例如運行上述輸出:

8230 the 
5067 and 
4140 of 
3651 to 
3017 a 
2660 in 
... 
440 when 
440 been 
428 which 
399 them 
385 what 

希望排除1或2個字符的填充詞等oftoa,和in以上?易:

awk -v RS='[[:alpha:]]+' ' 
    length(RT)>2 { cnt[tolower(RT)]++ } 
    END { 
     PROCINFO["sorted_in"] = "@val_num_desc" 
     for (word in cnt) { 
      print cnt[word], word 
      if (++c == 50) { 
       exit 
      } 
     } 
    } 
' pg98.txt 
8230 the 
5067 and 
2011 his 
1956 that 
1774 was 
1497 you 
1358 with 
.... 

與其他awks它會是一個while(match()) substr()環和輸出管道輸送到sort -n然後head

如果這不是你想要的,然後編輯你的問題,包括一些樣本輸入和預期的輸出,所以我們可以幫助你。

+1

偉大的解決方案!我正在考慮類似的事情。 – Firefly

+0

我遇到麻煩的一個問題是,我似乎無法管輸出,看到我的其他問題在這裏:http://stackoverflow.com/questions/35753818/how-to-correctly-pipe-commands-in -cygwin-using-windows – hjalpmig

+0

很明顯,這是與這個無關的另一個問題,你已經正確地發佈了它。一個建議,雖然 - 你說你在Cygwin在這個問題上,但是你說你在另一個問題從Windows執行。在說明您是從Cygwin還是從Windows執行命令時,在兩個問題中都要清楚明確。你可以/不能/不應該/不應該在Cygwin中完成與Windows完全無關,反之亦然。 –