2013-05-16 202 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()中的無限遞歸。我修正了上面的腳本。 –