我正在尝试分析包含层次结构中的行的文件。例如文件:
a b c
a b d
a B C
A B C
表示a
包含b
和B
,b
包含c
和d
,B
包含{ {1}}。 C
包含一个不同的A
,其中包含自己的B
。
这很像文件列表。
我想用分层的方括号将其格式化,例如:
C
我无法提出一种体面的方法来做到这一点。我以为AWK是我最好的选择,但是没有具体说明如何实现它。
我的输入实际上是文件列表。当然,如果需要,我当然可以用空格分隔字段,或者将其保留为a {
b {
c
d
}
B {
C
}
}
A {
B {
C
}
}
。这些文件是无序的,并在编译时通过检查从代码库生成。我想要的输出将是一个graphviz DOT文件,每个文件都包含在其自己的子图中。
因此输入:
/
输出应为
a/b/c
a/b/d
a/B/C
A/B/C
有人知道我如何完成此处理吗?我也可以使用其他工具,而不仅仅是AWK。
注意:尽管我可以根据需要预先计算最大深度,但是深度不是固定的。并非所有叶子的深度都相同。
答案 0 :(得分:2)
如果深度固定为3个水平
gawk -F/ '
{f[$1][$2][$3] = 1}
END {
n = 0
print "digraph {"
for (a in f) {
print " subgraph cluster_" a " {"
print " label = " a
for (b in f[a]) {
print " subgraph cluster_" b " {"
print " label = " b
for (c in f[a][b]) {
printf " node_%d [label=%s]\n", ++n, c
}
print " }"
}
print " }"
}
print "}"
}
' file
digraph {
subgraph cluster_A {
label = A
subgraph cluster_B {
label = B
node_1 [label=C]
}
}
subgraph cluster_a {
label = a
subgraph cluster_B {
label = B
node_2 [label=C]
}
subgraph cluster_b {
label = b
node_3 [label=c]
node_4 [label=d]
}
}
}
如果深度是任意的,事情就会变得复杂。
答案 1 :(得分:2)
我也可以使用其他工具,而不仅仅是AWK。
我提供了以下Python解决方案:
import sys
INDENT = ' '
NODE_COUNT = 1
def build(node, l):
x = l[0]
if x not in node:
node[x] = {}
if len(l) > 1:
build(node[x], l[1:])
def indent(s, depth):
print('%s%s' % (INDENT * depth, s))
def print_node(label, value, depth):
if len(value.keys()) > 0:
indent('subgraph cluster_%s {' % label, depth)
indent(' label = %s' % label, depth)
for child in value:
print_node(child, value[child], depth+1)
indent('}', depth)
else:
global NODE_COUNT
indent('node_%d [label=%s]' % (NODE_COUNT, label), depth)
NODE_COUNT += 1
def main():
d = {}
for line in sys.stdin:
build(d, [x.strip() for x in line.split()])
print('digraph {')
for k in d.keys():
print_node(k, d[k], 1)
print('}')
if __name__ == '__main__':
main()
结果:
$ cat rels.txt
a b c
a b d
a B C
A B C
$ cat rels.txt | python3 make_rels.py
digraph {
subgraph cluster_a {
label = a
subgraph cluster_b {
label = b
node_1 [label=c]
node_2 [label=d]
}
subgraph cluster_B {
label = B
node_3 [label=C]
}
}
subgraph cluster_A {
label = A
subgraph cluster_B {
label = B
node_4 [label=C]
}
}
}