Classifique as linhas enquanto agrupa as linhas recuadas com seus pais

Classifique as linhas enquanto agrupa as linhas recuadas com seus pais

Eu tenho uma lista de linhas semelhante ao índice de um livro, digamos

day
    satur-
    sun-
    holy-
night
    ball
    to-
eve
    election
    christmas

Agora quero classificar essas linhas da maneira óbvia: quero agrupar cada entrada “pai” ( day, night, eve) com suas respectivas entradas “filhas” recuadas ( satur-, sun-, …) e classificar esses grupos por sua entrada pai. Também quero classificar as entradas secundárias em qualquer grupo.

Assim, a saída desejada é:

day
    holy-
    satur-
    sun-
eve
    christmas
    election
night
    ball
    to-

Qual a melhor forma de conseguir isso usando ferramentas básicas do Unix como sort?

Responder1

Você pode escolher um caractere que provavelmente não ocorrerá em seu arquivo de texto, acrescentar o nome do pai + esse caractere a cada linha filho, classificar e remover o nome do pai e o separador de cada linha filho, por exemplo, com gnused e um caractere ascii baixo como\x02

sed '/^[^[:blank:]]/h;//!G;s/\(.*\)\n\(.*\)/\2\x02\1/' infile | sort | sed 's/.*\x02//'

Como funciona:
o primeiro sedfaz o seguinte:
/^[^[:blank:]]/h- copia linhas não recuadas (pais) sobre o espaço de espera
//!G- nas linhas recuadas (filhos) anexa o conteúdo do espaço de espera ao espaço padrão
s/\(.*\)\n\(.*\)/\2\x02\1/- troca as linhas no espaço padrão substituindo o \newline por \x02
depois disso, sorte remova tudo até e inclusive \x02com um 2ºsed 's/.*\x02//'

informação relacionada