
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 recuadas
split(/^(?=\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 awk
para 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