网址部分匹配

时间:2014-08-01 16:47:04

标签: shell awk sed scripting

我有两个文件: 档案1

http://www.hello.com        http://neo.com/peace/development.html, www.japan.com,  http://example.com/abc/abc.html
http://news.net             http://lolz.com/country/list.html,www.telecom.net, www.highlands.net, www.software.com
http://example2.com         http://earth.net, http://abc.gov.cn/department/1.html

文件2:

www.neo.com/1/2/3/names.html
http://abc.gov.cn/script.aspx
http://example.com/abc/abc.html

文件2是用于第2列的file1中的部分匹配的搜索URL。如果它具有部分匹配,则必须在文件1的第2列中返回第1列url和部分匹配URL,如下所示:

期望的输出:

http://www.hello.com    http://neo.com/peace/development.html, http://example.com/abc/abc.html
http://news.net
http://example2.com     http://abc.gov.cn/department/1.html

我尝试过这个脚本,它可以在第2列给出完全匹配的url模式,如下所示:

awk -F '[ \t,]' '
FNR == NR {
    a[$1]
    next
}
{    o = $1
    c = 0
    for(i = 2; i <= NF; i++)
        if($i in a)
            o = o (c++ ? ", " : "\t") $i
    print o
}' file2 file1

输出结果为:

http://www.hello.com    http://example.com/abc/abc.html
http://news.net
http://example2.com

有任何解决此问题的建议吗?

2 个答案:

答案 0 :(得分:0)

这是一个awk可执行脚本:

#!/usr/bin/awk -f

function getHost( url,        host ) {
    c = split( url, uarr, /[/]|:/ )
    for(j=1;j<=c;j++ ) {
        if( index( uarr[j], "." ) ) { host=uarr[j]; break }
    }
    return( host )
}

FNR==NR { host=getHost($1); if( host!="" ) hosts[host]; next }

# file2 FS="[[:space:]]|," file1
{
    end=""
    start = $1 "\t"
    for(i=2;i<=NF;i++) {
        f1h=getHost( $i )

        for( f2h in hosts ) {
            if( length( f2h ) > length( f1h ) )
                { long_host=f2h; short_host=f1h }
            else
                { long_host=f1h; short_host=f2h }

            if( short_host!="" && index( long_host, short_host ) ) {
                if( end!="" ) end = end ", "
                end = end $i
                break
            }
        }
    }
    print start (end!="" ? end : "")
}

如果它被称为awkochmod +x awko,则可以像以下一样运行:

awko file2 FS="[[:space:]]|," file1

至少有以下假设:

  • 您真正想要匹配的是来自网址
  • 的主机元素
  • 每个有效主机中至少有一个.
  • \t是找到的第一个和任何匹配字段之间的输出分隔符

故障:

  • getHost()函数将返回第一个元素,其中.为主机
  • file2个主机已加载到hosts数组
  • 在外部,在处理file1之前,,已添加到具有FS="[[:space:]]|,"的字段分隔符
  • file1解析中,第一个字段存储在start中,后续字段中的所有主机匹配都附加到end
  • 在比较主机之前,找到最长的主机并将其设置为long_host,将最短的设置为short_host
  • 如果在short_host中找到了long_host,请附加end并附上一些内务处理逗号。
  • 最后,为start
  • 中的每一行打印end以及通过匹配生成的所有file1

运行此选项会产生所需的输出,但警告\t当前始终会在输出中附加到$1(即使没有匹配项)。

答案 1 :(得分:0)

#!/usr/bin/awk -f
function gethostname(url) {
    sub(/^[a-z]+:\/+/, "", url)
    sub(/^www[.]/, "", url)
    sub(/\/.*$/, "", url)
    return url
}
BEGIN { FS = "[ ,\t\r]*" }
NR == FNR {
    a[gethostname($1)]++
    next
}
{
    t = ""
    for (i = 2; i <= NF; ++i) {
        if (gethostname($i) in a) {
            t = length(t) ? t ", " $i : $i
        }
    }
    print length(t) ? $1 "\t" t : $1
}

用法:

awk -f script.awk file2 file1

输出:

http://www.hello.com    http://neo.com/peace/development.html, http://example.com/abc/abc.html
http://news.net
http://example2.com     http://abc.gov.cn/department/1.html

您也可以制作统一的输出:

awk -f script.awk file2 file1 | column -t -s $'\t' -o '    '

请参阅man column

带有column的脚本版本:

#!/bin/sh    
awk -- '
    function gethostname(url) {
        sub(/^[a-z]+:\/+/, "", url)
        sub(/^www[.]/, "", url)
        sub(/\/.*$/, "", url)
        return url
    }
    BEGIN { FS = "[ ,\t\r]*" }
    NR == FNR {
        a[gethostname($1)]++
        next
    }
    {
        t = ""
        for (i = 2; i <= NF; ++i) {
            if (gethostname($i) in a) {
                t = length(t) ? t ", " $i : $i
            }
        }
        print length(t) ? $1 "|" t : $1
    }
' "$@" | column -t -s '|' -o '    '

用法;

sh script.sh file2 file1
相关问题