AWK рекурсивная древовидная структура - PullRequest
0 голосов
/ 26 ноября 2018

Я пытаюсь проанализировать файл, который содержит строки в иерархической структуре.Например, файл:

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 будет моей лучшей ставкой, но не смог понять, как это реализовать.

Context

Мой ввод - это фактически список файлов.Я могу, конечно, при необходимости разделить поля пробелами или оставить их с помощью /.Файлы неупорядочены и генерируются из кодовой базы во время компиляции посредством проверки.Мой желаемый вывод будет DOT-файл 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]
      }
  }
}

graphviz output

Кто-нибудь знает, как я мог выполнить эту обработку?Я открыт и для других инструментов, не только для AWK.

ПРИМЕЧАНИЕ. Глубина не фиксирована, хотя я мог бы предварительно рассчитать максимальную глубину, если это необходимо.Не все листья также будут на одной глубине.

Ответы [ 2 ]

0 голосов
/ 26 ноября 2018

Я открыт и для других инструментов, не только для 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]
    }
  }
}
0 голосов
/ 26 ноября 2018

Если глубина зафиксирована на 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]
    }
  }
}

Если глубина произвольная, все усложняется.

...