Bash AWK递归树结构
我试图解析一个文件,它包含层次结构中的行。例如,文件:Bash AWK递归树结构,bash,awk,graphviz,dot,Bash,Awk,Graphviz,Dot,我试图解析一个文件,它包含层次结构中的行。例如,文件: a b c a b d a B C A B C 表示a包含b和b,b包含c和d,b包含cA包含一个不同的B,它包含自己的C 这很像一个文件列表 我想以一种分层次的方式对其进行格式化,如: a { b { c d } B { C } } A { B { C } } 我想不出一个像样的方法来做这件事。我原以为AWK是我最好的选择,
a b c
a b d
a B C
A B C
表示a
包含b
和b
,b
包含c
和d
,b
包含c
<代码>A包含一个不同的B
,它包含自己的C
这很像一个文件列表
我想以一种分层次的方式对其进行格式化,如:
a {
b {
c
d
}
B {
C
}
}
A {
B {
C
}
}
我想不出一个像样的方法来做这件事。我原以为AWK是我最好的选择,但没想到如何真正实现它
上下文
我的输入实际上是一个文件列表。如果需要,我当然可以用空格分隔字段,或者用/
保存它们。这些文件是无序的,在编译时通过检查从代码库生成。我想要的输出是一个graphviz点文件,每个文件都包含在它自己的子图中
因此,对于输入:
a/b/c
a/b/d
a/B/C
A/B/C
输出将是
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]
}
}
}
有人知道我怎么处理吗?我对其他工具也持开放态度,不仅仅是AWK
注意:深度不是固定的,但如果需要,我可以预先计算最大深度。也不是所有的叶子都在同一个深度。如果深度固定在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
如果深度是任意的,事情就会变得复杂。如果深度固定在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
如果深度是任意的,事情就会变得复杂
我对其他工具也持开放态度,不仅仅是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]
}
}
}
我对其他工具也持开放态度,不仅仅是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]
}
}
}
如果您有
a/b/c
和a/b/d
,它会是什么样子?i、 e.子集群中有2个叶节点?我刚刚编辑了示例以显示。是否可以有3个以上的级别,如a b d x
或a b d p q r
?在结尾添加了一个注释,并作了进一步的说明,但可以有3个以上的级别,并且在任何级别都可以有叶。您提到的输入是无序的。这是否意味着a b d p q r
记录可以位于w x y z
之后,而a b c
可以位于文件的顶部?如果您有a/b/c
和a/b/d
,它会是什么样子?i、 e.子集群中有2个叶节点?我刚刚编辑了示例以显示。是否可以有3个以上的级别,如a b d x
或a b d p q r
?在结尾添加了一个注释,并作了进一步的说明,但可以有3个以上的级别,并且在任何级别都可以有叶。您提到的输入是无序的。这是否意味着abdpqr
记录也可以位于wxyz
之后,而abc
可以位于文件的顶部?不幸的是,深度是任意的,所以事情很复杂。但对于固定深度,这是一个很好的解决方案!不幸的是,深度是任意的,所以事情很复杂。但对于固定深度,这是一个很好的解决方案!出于我的目的,这项工作需要修改。它不像我希望的那样干净,但是完成了工作:)这对我来说是经过修改的。它不像我希望的那么干净,但却完成了任务:)