缩进线(树)到路径般的线条 [英] Indented lines (tree) to path-like lines

查看:99
本文介绍了缩进线(树)到路径般的线条的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有像下一个结构输入文件:

I have input files with the structure like the next:

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

每个级别由2个空格缩进。所需的输出是:

Each level is indented by 2 spaces. The needed output is:

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

它就像一个文件系统,如果下一行有较大的缺口,当前的就像是一个目录,当有相同的缩进它就像一个文件。需要打印的文件。

It is like a filesystem, if the next line have bigger indentation, the current one is like a "directory" and when have same indentation it is like a "file". Need print full paths of "files".

试图解决这个没有任何高级语言,如蟒蛇 perl的 - 只有基本的bash命令

Trying to solve this without any high-level language, like python, perl - with only basic bash commands.

我目前的code /想法是基于递归函数调用和堆栈的工作,但与逻辑的问题。在code当前输出下一个:

My current code/idea is based on recursive function call and working with a stack, but have problem with the "logic". The code currently outputs the next:

a1 b1 c1
a1 b1
a1

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

只有1号线是确定 - 所以在处理递归是错误的...

only the 1st line is OK - so handling the recursion is wrong...

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
)

Sry基因为长code - 任何人可以帮助

Sry for the long code - can anybody help?

推荐答案

有趣的问题。

这AWK(可能是一行程序)命令做这项工作:

this awk (could be one-liner) command does the job:

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

您可以在上面看到,有重复的codeS,你可以解压缩到一个功能,如果你喜欢。

you can see above, there are duplicated codes, you can extract them into a function if you like.

测试与您的数据:

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    

这篇关于缩进线(树)到路径般的线条的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆