Classifique o arquivo por grupo de linhas

Classifique o arquivo por grupo de linhas

Se eu tiver um arquivo com conteúdo semelhante a:

FirstSection
    Unique first line in first section
    Unique second line in first section

SecondSection
    Unique first line in second section
    Unique second line in second section

...

NthSection
    Unique first line in Nth section
    Unique second line in Nth section

É possível usar comandos unix (por exemplo, sort, awk) para classificar o arquivo em ordem alfabética pela primeira linha não recuada em cada grupo de três linhas, mantendo as linhas recuadas no grupo existente?

Responder1

Usando Perl, você poderia executar algo como:

  • sorver o arquivo ( perl -0n)
  • divida a entrada por linhas não recuadassplit(/^(?=\S)/m)
  • classificar e imprimir

perl -0ne 'print sort split(/^(?=\S)/m) ' ex 

Responder2

Primeiro, o sed coloca cada seção em uma única linha, usando o texto <EOL>como delimitador entre as linhas da seção. Então estou classificando as seções e usando o segundo sed para reverter cada uma <EOL>para uma nova linha.

sed -r ':r;$!{N;br};s:\n([[:blank:]])(\1*):<EOL>\1\2:g' file|sort|sed -r '/^$/d;:l;G;s:(.*)<EOL>(.*)(\n):\1\3\2:;tl;$s:\n$::'

Não escolhi um caractere como delimitador, pois o arquivo de entrada pode tê-lo, então usei <EOL>.

Saída:Adicionei uma nova linha após cada seção, exceto a última, para recriar o estilo do arquivo de entrada.

FirstSection
    Unique first line in first section
    Unique second line in first section

NthSection
    Unique first line in Nth section
    Unique second line in Nth section

SecondSection
    Unique first line in second section
    Unique second line in second section

Responder3

com GNU awkpara o asort()e PROCINFO["sorted_in"]poderíamos manter cada grupo de registros em um array associado ao awk com base na quebra de linha entre cada grupo; em seguida, classifique a matriz asort()e imprima todos os grupos em um loop for.

awk '/^$/{ ++grpNr; next }
{ groups[grpNr]=(groups[grpNr]==""? "" : groups[grpNr] RS) $0 }
END{ asort(groups); 
     for(grp in groups) print groups[grp]
}'  infile

observação: você pode usar PROCINFO["sorted_in"]element para definir qual tipo de classificação você precisa; por exemplo, PROCINFO["sorted_in"]="@val_str_desc"classificará ovalorue do nosso array comostrdentro e dentrodescordem.


Ou com any awk(para produzir blocos de registros delimitados por Nul) + sort -z(para classificar com base no caractere Nul e não na nova linha) + tr(para remover o caractere Nul adicionado anteriormente pelo awk):

<infile awk '/^$/{ ++grpNr; next }
{ groups[grpNr]=(groups[grpNr]==""? "\0" : groups[grpNr] RS) $0 }
END{ for(grp in groups) print groups[grp] }' |sort -z |tr -d '\0'

testando em um arquivo de entrada como:

BFirstSection
    Unique first line in first section
    Unique second line in first section

DSecondSection
    Unique first line in second section
    Unique second line in second section

Aanothersection...
    ...
    ...

CfourthSection
    Unique first line in Nth section
    Unique second line in Nth section

você obterá uma saída como:

Aanothersection...
    ...
    ...
BFirstSection
    Unique first line in first section
    Unique second line in first section
CfourthSection
    Unique first line in Nth section
    Unique second line in Nth section
DSecondSection
    Unique first line in second section
    Unique second line in second section

informação relacionada