从根连接分层路径
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
我有一个如下所示的地址文件
$ 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