5

使用这个文件,我想打印一个包依赖树,给定一个基础包。例如,以 Bash 包为例

@ bash
# few lines removed
requires: coreutils libintl8 libncursesw10 libreadline7 _update-info-dir cygwin

我想要所需包的类似查找的输出,部分示例

bash
bash coreutils
bash coreutils libattr1
bash coreutils libattr1 libintl8
bash coreutils libattr1 libintl8 libiconv2
bash coreutils libattr1 libintl8 _autorebase
bash coreutils libattr1 libintl8 _autorebase rebase
bash coreutils libattr1 libintl8 _autorebase rebase dash
bash coreutils libattr1 libintl8 _autorebase rebase dash cygwin
bash coreutils libattr1 libintl8 _autorebase rebase dash cygwin base-cygwin

我有这个命令,但它不递归

#!awk -f
$1 == "@" {
  pkg = $2
}
$1 == "requires:" {
  for (i=2; i<=NF; i++)
    reqs[pkg][i-1] = $i
}
END {
  query = "bash"
  for (pkg in reqs[query]) {
    print reqs[query][pkg]
  }
}
4

3 回答 3

6

使用 Perl 并且没有注释:

perl -lne '
  $k = $1 if /@\s*(\S+)/; 
  @r=split(); shift @r; $r{$k} = [@r] if /requires:/;
  END{
    $p = "bash"; @l = ( [$p, 0] );
    while ($p = pop @l) {
        next if $d{$p->[0]}++;
        print " " x $p->[1] . $p->[0];
        for $d(@{$r{$p->[0]}}) {
            push @l, [ $d, $p->[1]+1 ];
        }
    }
  }' setup.ini

awk 版本:

awk '/^@ / { split($0, b); k = b[2]; }
     /^requires: / { a[k] = $0; }
     END {
       p[1] = "bash"; d["bash"] = 0;
       while (length(p)) {
           key = p[length(p)]; depth = d[key]; delete p[length(p)];
           if (!s[key]++) {
               printf "%*s %s\n", depth, "", key;
               split(a[key], r); delete r[1];
               for (req in r) {
                   p[length(p) + 1] = r[req]; d[r[req]] = depth + 1;
               }
           }
       }
     }
' setup.ini
于 2013-05-16T06:08:40.563 回答
3

将 GNU awk 用于真正的多维数组(但显然​​可以针对其他 awk 进行调整):

$ cat tst.awk
/^@/         { pkg = $2 }
/^requires:/ { for (i=2;i<=NF;i++) reqs[pkg][$i]  }
END          { prtPkg(root) }

function prtPkg(pkg,    req) {
    if (!seen[pkg]++) {
        printf "%*s%s\n", indent, "", pkg
        indent += 2
        if (pkg in reqs)
            for (req in reqs[pkg])
                prtPkg(req)
        indent -= 2
    }
}

.

$ cat file3
@ bash
whatever
requires: libgcc1 libintl8 libncursesw10 libreadline7 _update-info-dir

@ libintl8
whatever
requires: libiconv2 bash common

@ libgcc1
whatever
requires: _autorebase common

.

$ awk -v root="bash" -f tst.awk file3
bash
  libncursesw10
  libgcc1
    _autorebase
    common
  _update-info-dir
  libreadline7
  libintl8
    libiconv2

以下是您想要的新输出格式所需的内容:

$ cat file3
@ bash
requires: libgcc1 libintl8 libncursesw10 libreadline7

@ libncursesw10
requires: libgcc1 libstdc++6 terminfo libreadline7

.

$ cat tst.awk
/^@/         { pkg = $2 }
/^requires:/ { for (i=2;i<=NF;i++) reqs[pkg][i-1]=$i  }
END          { setMinDepth(root); prtPkg(root) }

function setMinDepth(pkg,    req, i) {
    depth++
    minDepth[pkg] = ( !(pkg in minDepth) || (depth < minDepth[pkg]) ?
                        depth : minDepth[pkg])

    if (depth == minDepth[pkg]) {
        if (pkg in reqs)
            for (i=1; i in reqs[pkg]; i++) {
                req = reqs[pkg][i]
                setMinDepth(req)
            }
    }
    depth--
}

function prtPkg(pkg,    req, i) {
    depth++
    if ( (depth == minDepth[pkg]) && (!seen[pkg]++) ) {
        printf "%*s%s\n", indent, "", pkg
        indent += 2
        if (pkg in reqs)
            for (i=1; i in reqs[pkg]; i++) {
                req = reqs[pkg][i]
                prtPkg(req)
            }
        indent -= 2
    }
    depth--
}

.

$ awk -v root="bash" -f tst.awk file3
bash
  libgcc1
  libintl8
  libncursesw10
    libstdc++6
    terminfo
  libreadline7
于 2014-05-20T18:41:29.270 回答
0
#!/usr/bin/awk -f
@include "join"
$1 == "@" {
  apg = $2
}
$1 == "requires:" {
  for (z=2; z<=NF; z++)
    reqs[apg][z-1] = $z
}
END {
  prpg("bash")
}
function smartmatch(small, large,    values) {
  for (each in large)
    values[large[each]]
  return small in values
}
function prpg(fpg) {
  if (smartmatch(fpg, spath)) return
  spath[length(spath)+1] = fpg
  print join(spath, 1, length(spath))
  if (isarray(reqs[fpg]))
    for (each in reqs[fpg])
      prpg(reqs[fpg][each])
  delete spath[length(spath)]
}

资源

于 2014-11-11T09:29:51.780 回答