У меня есть адресный файл, как показано ниже
$ 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
Любое другое решение оболочки также приветствуется!
@adir мне подходит любое решение для оболочки ..
если любое решение оболочки подходит, то пометка вопроса только perl значительно ограничит количество ответов, которые вы получите не на Perl.
@EdMorton.. я пометил их... но Брайан Д. Фой отредактировал и удалил их..
Обновлено: Используя регулярное выражение с 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
Если вы не придирчивы к порядку, единственное решение — продолжать удалять с конца до тех пор, пока вы не сможете.
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
спасибо @ikegami .. за первое .. как мы можем подключиться к другим инструментам Unix, чтобы разобраться с этим .. просто любопытно.
С помощью символа трубы. ... | ...
:-) извините, я имел в виду, будет ли perl -F, -lane'do { print join ",", @F } while $F[0] =~ s{^.+\K/[^/]*\z}{}' hier.dat | sort -k2 -t,
работать идеально?
Работает для вашего небольшого набора входных тестов:
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
отлично!.. он отлично работает.. можете ли вы объяснить, как работает регулярное выражение
Как здесь связан питон?