2012-07-18 37 views
17

我有一個文件叫其中包含一些域。例如:如何在正則表達式中使用awk變量?

google.com 
facebook.com 
... 
yahoo.com 

而且我有一個名爲網站其中包含了一些網站的網址和數字的另一個文件。例如:

image.google.com 10 
map.google.com  8 
... 
photo.facebook.com 22 
game.facebook.com 15 
.. 

現在我要計算每個域的url編號。例如:google.com已有10 + 8。所以我寫了一個awk腳本是這樣的:

BEGIN{ 
    while(getline dom < "./domain" > 0) { 
    domain[dom]=0; 
    } 
    for(dom in domain) { 
    while(getline < "./site" > 0) { 
     if($1 ~/$dom$) #if $1 end with $dom { 
     domain[dom]+=$2; 
     } 
    } 
    } 
} 

但代碼if($1 ~/$dom$)不運行像我想要的。因爲正則表達式中的變量$ dom是從字面上解釋的。所以,第一個問題是:

有沒有什麼辦法在正則表達式中使用變量$dom

然後,我是新來的寫作腳本

有沒有更好的辦法來解決我的問題嗎?

回答

15

首先,變量是dom$dom - 考慮$作爲一個經營者,以提取存儲在變量dom

其次列數的值,awk將不插//之間有什麼 - 那只是一個字符串。

你想要match()功能,其中第二個參數可以是被視爲正則表達式的字符串:使用

awk ' 
    FNR == NR {domain[$1] = 0; next} 
    { 
    for (dom in domain) { 
     if (match($1, dom "$")) { 
     domain[dom] += $2 
     break 
     } 
    } 
    } 
    END {for (dom in domain) {print dom, domain[dom]}} 
' domain site 
+0

中肯所有這些談論變量是如何沒有前綴與$,它更好地解釋(IMO)awk中的$ means字段,所以無論dom的值是多少,$ dom都將意味着字段。 awk中的變量用於不加引號且不帶$。它不是殼! – 2018-01-04 09:47:56

1

方式一:

if (match($1, dom "$")) {...} 

我將如下代碼的解決方案awk腳本:

BEGIN { 
    FS = "[. ]" 
    OFS = "." 
} 

FNR == NR { 
    domain[$1] = $0 
    next 
} 

FNR < NR { 
    if ($2 in domain) { 
     for (i = 2; i < NF; i++) { 
      if ($i != "") { 
       line = (line ? line OFS : "") $i 
      } 
     } 
     total[line] += $NF 
     line = "" 
    } 
} 

END { 
    for (i in total) { 
     printf "%s\t%s\n", i, total[i] 
    } 
} 

運行喜歡:

awk -f script.awk domain.txt site.txt 

結果:

facebook.com 37 
google.com 18 
+0

如果您在「網站」文件中獲得了像「first.second.example.com」這樣的域名,則此方法無法正常工作。 – 2012-07-18 16:00:31

+0

@glennjackman,是的,你是對的。我不認爲:-( – Steve 2012-07-18 22:59:38

1

您顯然希望在domain閱讀site文件一次,每個條目一次也沒有。然而,修復這個問題是微不足道的。

同樣,awk(除字段$0 .. $9等之外的變量)前綴爲$。特別是,$dom是由變量dom標識的字段編號(通常,這將是0,因爲域字符串不會轉換爲任何其他編號)。

我認爲你需要找到一種方法來從site文件中讀取數據。我不確定您是否需要處理國家/地區域名(例如bbc.co.uk)以及GTLD中的網站(google.com等)。假設你不處理的國家域名,您可以使用此:

BEGIN { 
    while (getline dom < "./domain" > 0) domain[dom] = 0 
    FS = "[ .]+" 
    while (getline < "./site" > 0) 
    { 
     topdom = $(NF-2) "." $(NF-1) 
     domain[topdom] += $NF   
    } 
    for (dom in domain) print dom " " domain[dom] 
} 

在第二while循環,有NF領域; $NF包含計數,並且$1 .. $(NF-1)包含該域的組件。因此,topdom最終包含頂級域名,然後用於索引到在第一個循環中初始化的數組中。

鑑於該問題(減去點的線)的數據,輸出爲:

yahoo.com 0 
facebook.com 37 
google.com 18 
17

awk可以對匹配的變量,如果你不使用正則表達式//標記。

if ($0 ~ regex){ print $0; }

在這種情況下,建立所需要的正則表達式作爲一個字符串

regex = dom"$" 

然後匹配對regex變量

if ($1 ~ regex) { 
    domain[dom]+=$2; 
} 
相關問題