从根连接分层路径

concatenating hierarchical paths from the root

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

$ 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

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

编辑: 通过将正则表达式与 awk 结合使用,您能否尝试以下操作。

awk '
BEGIN{
  FS=OFS=","
}
{
  val=""
  while(match(,/^\/[^/]*/)){
    val=(val?val:"")substr([=10=],RSTART,RLENGTH)
    print val,$NF
    [=10=]=substr([=10=],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

如果您对顺序不挑剔,唯一的解决办法是从末尾继续删除,直到您不能。

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

适用于您的一小组输入测试:

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

或者:

perl -ne'@a=($_);unshift@a,$_ while s|(.+)/.*,|,|;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