2013-05-16 150 views
4

使用this file,我想打印一个 包的依赖关系树,给定一个基本包。例如,拿 bash包打印程序包依赖关系树

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

我想所需 包find-like输出部分例如

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] 
    } 
} 
+1

我将开始与BEGIN {RS = “@”; FS = “\ n”}和比较$ i到 “要求:” 凡$ a1将是使用的名称在你的关联数组和某个字段中(使用for循环或其他)将以require - 使用substr在“:”之前移除并将其作为值存储....然后在END中,将使用关联数组递归地打印值 - 但要注意循环依赖关系 – technosaurus

回答

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)] 
} 

Source

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 
+7

@StevenPenny,在答案中增加了一个awk版本。 – perreal

4

利用GNU AWK为真正的多d阵列(但显然可以调整了其他awks):

$ 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 
+0

FYI功能上,两种保存'reqs [pkg]'的方法之间的区别在于,如果您使用'reqs [pkg] [$ i]',它会删除重复项,但不会保留顺序,而'reqs [pkg] [i-1 ] = $ i'不会删除重复项目,但会保留顺序。如果您想使用第二种方法并删除重复项,最简单的方法是在读取期间检查第二个tmp“seen”数组'seenFld [$ i] ++',然后删除,然后使用tmp计数变量'++ j'而不是'i-1'作为数组索引。 –

+0

您可能在文件中声明了循环依赖项。这会导致setMinDepth()中的无限递归。我修正了上面的脚本。 –