2012-07-18 33 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; 
} 
相关问题