bash - 缩进线(树)到类似路径的线

标签 bash recursion tree

我有如下结构的输入文件:

a1
  b1
    c1
    c2
    c3
  b2
    c1
      d1
      d2
  b3
  b4
a2
a3
  b1
  b2
    c1
    c2

每一层缩进两个空格。所需的输出是:

a1/b1/c1
a1/b1/c2
a1/b1/c3
a1/b2/c1/d1
a1/b2/c1/d2
a1/b3
a1/b4
a2
a3/b1
a3/b2/c1
a3/b2/c2

它就像一个文件系统,如果下一行有更大的缩进,当前的就像一个“目录”,当有相同的缩进时,它就像一个"file"。需要打印"file"的完整路径。

尝试在没有任何高级语言的情况下解决这个问题,例如 pythonperl - 仅使用基本的 bash 命令。

我当前的代码/想法是基于递归函数调用和使用堆栈,但“逻辑”有问题。代码当前输出下一个:

a1 b1 c1
a1 b1
a1

DD: line 8: [0-1]: bad array subscript

只有第一行没问题 - 所以处理递归是错误的...

input="ifile.tree"

#stack array
declare -a stack

#stack manipulation
pushstack() { stack+=("$1"); }
popstack() { unset stack[${#stack[@]}-1]; }
printstack() { echo "${stack[*]}"; }

#recursive function
checkline() {
    local uplev=$1

    #read line - if no more lines - print the stack and return
    read -r level text || (printstack; exit 1) || return

    #if the current line level is largest than previous level
    if [[ $uplev < $level ]]
    then
        pushstack "$text"
        checkline $level    #recurse
    fi

    printstack
    popstack
}

# MAIN PROGRAM

# change the input from indented spaces to
# level_number<space>text
(
    #subshell - change IFS
    IFS=,
    while read -r spaces content
    do
        echo $(( (${#spaces} / 2) + 1 )) "$content"
    done < <(sed 's/[^ ]/,&/' < "$input")

) | (   #pipe to another subshell
    checkline 0 #recurse by levels
)

对不起,代码太长了 - 有人能帮忙吗?

最佳答案

有趣的问题。

这个 awk(可以是一行)命令完成了这项工作:

awk -F'  ' 'NF<=p{for(i=1;i<=p;i++)printf "%s%s", a[i],(i==p?RS:"/")
            if(NF<p)for(i=NF;i<=p;i++) delete a[i]}
            {a[NF] =$NF;p=NF }
            END{for(i=1;i<=NF;i++)printf "%s%s", a[i],(i==NF?RS:"/")}' file

可以看到上面有重复的代码,喜欢的可以抽成一个函数

用你的数据测试:

kent$  cat f
a1
  b1
    c1
    c2
    c3
  b2
    c1
      d1
      d2
  b3
  b4
a2
a3
  b1
  b2
    c1
    c2

kent$  awk -F'  ' 'NF<=p{for(i=1;i<=p;i++)printf "%s%s", a[i],(i==p?RS:"/")
if(NF<p)for(i=NF;i<=p;i++) delete a[i]}
{a[NF] =$NF;p=NF }END{for(i=1;i<=NF;i++)printf "%s%s", a[i],(i==NF?RS:"/")} ' f
a1/b1/c1
a1/b1/c2
a1/b1/c3
a1/b2/c1/d1
a1/b2/c1/d2
a1/b3
a1/b4
a2
a3/b1
a3/b2/c1
a3/b2/c2    

关于bash - 缩进线(树)到类似路径的线,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22647847/

相关文章:

sql-server-2005 - T-SQL CTE错误: Types don't match between the anchor and the recursive part

bash - 判断用户当前tty是否运行图形界面

php - bash 脚本从命令行运行,但不是从 cron 运行

c - 递归检查C中方程的括号平衡

c# - 在所有子目录中查找具有特定扩展名的文件数

linux - 如何将路径列表可视化为树?

algorithm - 维基百科的广度优先搜索示例 : How is a parentless node reached?

javascript - 使用javascript获取子文件夹名称

bash - 我可以在不修改现有所有者/组的情况下在 Bash 中为特定组/用户添加权限吗?

bash - 用于创建 Db 和集合的 Mongo bash 脚本