加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

bash – 缩进的行(树)到路径的行

发布时间:2020-12-15 22:09:43 所属栏目:安全 来源:网络整理
导读:我输入的文件结构如下: a1 b1 c1 c2 c3 b2 c1 d1 d2 b3 b4a2a3 b1 b2 c1 c2 每个级别缩进2个空格.所需的输出是: a1/b1/c1a1/b1/c2a1/b1/c3a1/b2/c1/d1a1/b2/c1/d2a1/b3a1/b4a2a3/b1a3/b2/c1a3/b2/c2 它就像一个文件系统,如果下一行有更大的缩进,当前的那个
我输入的文件结构如下:

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

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

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

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

尝试在没有任何高级语言的情况下解决这个问题,比如python,perl – 只有基本的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",(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",(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",(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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读