AWK:根据与输入文件

时间:2016-08-03 13:05:03

标签: awk graph

问题

所以我有一个包含三个字段的输入文件。它基本上是一个描述有向图类型的列表。第一个字段是起始节点,第二个连接类型(在这种情况下有多个),最后一个是投影到的节点。

问题是,这是一个非常大且不守规矩的直接图,我只对某些路径感兴趣。所以我想提供一个输入文件,其中包含我关心的节点名称。如果在图形文件的第一个或第三个字段中提到节点,那么我想要整个记录(因为路径类型可能会有所不同)。

问题

如何仅提取有向图的某些记录?

奖金,如何仅提取最多一个邻居加入感兴趣节点的那些路径(即感兴趣的节点可以是第二个最近邻居)。

请求

我正在努力改进我的AWK编程,这就是为什么1)我想在AWK中做到这一点2)我非常感谢代码的详细解释:)

问题示例

输入文件:

A  
C  
D  

要解析的文件:

A -> B  
A -> C  
A -> D  
B -> A  
B -> D  
C -> E  
D -> F  
E -> B  
E -> F  
F -> C  

...

输出:

A -> B  
A -> C  
A -> D  
B -> A   
B -> D    
C -> E   
D -> F 
F -> C

奖金示例:

 A -> B -> D  -> F -> C

2 个答案:

答案 0 :(得分:2)

如果我理解你的问题,那么这样做:

awk 'NR==FNR { data[$1] = 1; next } $1 in data || $3 in data { print }' graph[12]

工作原理:在阅读第一个文件时,将所有有趣的节点添加到data。在读取第二个文件时,只打印第一个字段或第三个字段在data中的行,即是一个有趣的节点。

答案 1 :(得分:0)

寻求奖金:

function left(str) { # returns the leftmost char of a given edge (A -> B)
    return substr(str,1,1)
}
function right(str) { # returns the rightmost...
    return substr(str,length(str),1)
}

function cmp_str_ind(i1, v1, i2, v2) # array travese order function
{ # this forces the start from the node in the beginning of input file
    if(left(i1)==left(a)&&left(i2)!=left(a)) # or leftmost value in a
        return -1
    else if(left(i2)==left(a)&&left(i1)!=left(a))
        return 1
    else if(i1 < i2)
        return -1
    return (i1 != i2)
}

function trav(a,b,c,d) { # goes thru edges in AWK order
#   print "A:"a," C:"c," D:"d
    if(index(d,c)||index(d,right(c))) {
        return ""
    }
    d=d", "c  # c holds the current edge being examined
    if(index(a,right(c))) { # these edges affect a
#       print "3:"c
        sub(right(c),"",a)
        if(a=="") { # when a is empty, path is found
            print d # d has the traversed path
            exit
        }
        for (i in b) {
            if(left(i)==right(c)) # only try the ones that can be added to the end
                trav(a,b,i,d)
        }
        a=a""right(c)
    } else {
#   print "4:"c
        for (i in b)
            if(left(i)==right(c))
                trav(a,b,i,d)
    }
}
BEGIN { # playing with the traverse order
    PROCINFO["sorted_in"]="cmp_str_ind"
}  
NR==FNR {
    a=a""$0 # a has the input (ADC)
    next
}
{
    b[$0]=$0 # b has the edges
}
END {           # after reading in the data, recursively test every path
    for(i in b) # candidate pruning the unfit ones first. CLR or Dijkstra 
        if(index(a,left(i))) {        # were not consulted on that logic.
#           print "3: "i
            sub(left(i),"",a)
            trav(a,b,i,left(i))
            a=a""left(i)
        }
        else {
#           print "2: "i
            trav(a,b,i,left(i))
        }
}
$ awk -f graph.awk input parse
A, A -> D, D -> F, F -> C

如果您取消注释BEGIN部分,则会获得A, A -> B, B -> D, D -> F, F -> C。我知道,我应该更多地研究它并更好地评论它,但它在这里午夜。也许明天。