代码之家  ›  专栏  ›  技术社区  ›  stack0114106

从根连接分层路径

  •  0
  • stack0114106  · 技术社区  · 4 年前

    我有一个地址文件,如下所示

    $ cat hier.dat
    /City-A/Streetx/House1,100
    /City-B/Streety/House2,200
    $
    

    我需要从一开始就通过扩展层次结构来生成更多的行。所需输出为

    /City-A,100
    /City-A/Streetx,100
    /City-A/Streetx/House1,100
    /City-B,200
    /City-B/Streety,200
    /City-B/Streety/House2,200
    

    下面的perl命令在逻辑上看起来是正确的,但它没有给出正确的结果

    $ perl -F, -lane ' $s="";  while($F[0]=~/\G\/.+?\//g) {$s.=$&; print $s.",".$F[1] } ' hier.dat
    /City-A/,100
    /City-B/,200
    

    任何其他外壳解决方案也欢迎!

    0 回复  |  直到 4 年前
        1
  •  3
  •   ikegami Gilles Quénot    4 年前

    如果你对订单不挑剔,一个单一的解决方案是从最后开始删除,直到你不能。

    do { print join ",", @F } while $F[0] =~ s{^.+\K/[^/]*\z}{}
    
    $ perl -F, -lane'do { print join ",", @F } while $F[0] =~ s{^.+\K/[^/]*\z}{}' hier.dat
    /City-A/Streetx/House1,100
    /City-A/Streetx,100
    /City-A,100
    /City-B/Streety/House2,200
    /City-B/Streety,200
    /City-B,200
    

    当然,这很容易纠正。

    do { push @a, join ",", @F } while $F[0] =~ s{^.+\K/[^/]*\z}{};
    print for reverse splice @a
    
    $ perl -F, -lane'
       do { push @a, join ",", @F } while $F[0] =~ s{^.+\K/[^/]*\z}{};
       print for reverse splice @a
    ' hier.dat
    /City-A,100
    /City-A/Streetx,100
    /City-A/Streetx/House1,100
    /City-B,200
    /City-B/Streety,200
    /City-B/Streety/House2,200
    

    “有趣”的替代方案:

    $F[0] =~ m{
       ^ (?: /[^/]++ )+?
       (?{ print join ",", $&, $F[1] })
       (*FAIL)
    }x
    
    $ perl -F, -lane'$,=",";$F[0]=~m{^(/[^/]++)+?(?{print$&,$F[1]})(?!)}' hier.dat
    /City-A,100
    /City-A/Streetx,100
    /City-A/Streetx/House1,100
    /City-B,200
    /City-B/Streety,200
    /City-B/Streety/House2,200
    
        2
  •  3
  •   RavinderSingh13 Nikita Bakshi    4 年前

    编辑: 通过使用正则表达式 awk ,你能试试下面的吗。

    awk '
    BEGIN{
      FS=OFS=","
    }
    {
      val=""
      while(match($1,/^\/[^/]*/)){
        val=(val?val:"")substr($0,RSTART,RLENGTH)
        print val,$NF
        $0=substr($0,RSTART+RLENGTH)
      }
    }
    '  Input_file
    


    如果你同意的话 awk ,你能试着用GNU中显示的示例编写和测试以下内容吗 awk .

    awk '
    BEGIN{
      FS="[/,]"
      OFS="/"
    }
    {
      val=""
      for(i=2;i<NF;i++){
        val=(val?val:"")OFS $i
        print val","$NF
      }
    }'  Input_file
    

    说明: 对上述内容进行了详细解释。

    awk '                       ##Starting awk program from here.
    BEGIN{                      ##Starting BEGIN section of this program from here.
      FS="[/,]"                 ##Setting field separator as / OR , here.
      OFS="/"                   ##Setting output field separator as / here.
    }
    {
      val=""                    ##Nullifying val here.
      for(i=2;i<NF;i++){        ##Going through fields of current line from 2nd field to 2nd last field.
        val=(val?val:"")OFS $i  ##Creating val with current field value and keep concatenating it in its own value.
        print val","$NF         ##Printing val comma and last field here.
      }
    }
    ' Input_file                ##Mentioning Input_file name here. 
    

    所示样本的输出如下。

    /City-A,100
    /City-A/Streetx,100
    /City-A/Streetx/House1,100
    /City-B,200
    /City-B/Streety,200
    /City-B/Streety/House2,200
    
        3
  •  2
  •   Kjetil S.    4 年前

    适用于您的小型输入测试集:

    perl -ne'@a=($_);unshift@a,$_ while s|(.+)/.*,|$1,|;print@a' /tmp/test.data
    

    或者:

    perl -ne'@a=($_);unshift@a,$_ while s|(.+)/.*,|$1,|;print@a' <<.
    /City-A/Streetx/House1,100
    /City-B/Streety/House2,200
    .
    

    结果:

    /City-A,100
    /City-A/Streetx,100
    /City-A/Streetx/House1,100
    /City-B,200
    /City-B/Streety,200
    /City-B/Streety/House2,200