Como classificar separadamente as linhas em vários "pedaços" separados por cabeçalhos?

3

Esta questão é complementar a esta: Classifique os pacotes de linhas em ordem alfabética . Depois de responder lá, descobri que eu havia entendido mal a questão e resolvido outro problema. Não querendo que minha solução seja esquecida, estou postando o problema aqui (e minha solução abaixo).

Considere um texto como:

[ProfileB]
param3=z
param2=y
param1=x
[ProfileA]
param1=k
param3=l
param2=

Eu preciso classificar os parâmetros dentro de cada bloco [Profile*] separadamente. O exemplo acima deve ser classificado para isso:

[ProfileB]
param1=x
param2=y
param3=z
[ProfileA]
param1=k
param2=
param3=l

Como posso fazer isso com as ferramentas padrão do Unix / Linux?

    
por Kamil Maciorowski 04.06.2018 / 14:49

1 resposta

2

Isso funciona no meu Debian:

sed '1 ! s/^\[/\x00\[/g' |
split -t '
sed '1 ! s/^\[/\x00\[/g' |
split -t '%pre%' -l 1 --filter='
   tr -d "%pre%" |
   { IFS="" read; printf "%s\n" "$REPLY"; sort; }
'
' -l 1 --filter=' tr -d "%pre%" | { IFS="" read; printf "%s\n" "$REPLY"; sort; } '

Para trabalhar com arquivo (s), use redirecionamento (s), por exemplo. { sed … ; } <input.txt >output.txt , em que sed … é o comando inteiro.

O procedimento é o seguinte:

  1. sed insere caractere nulo antes de cada [ que está no início de uma linha, a menos que a linha seja a primeira. Desta forma, os caracteres nulos separam os perfis.
  2. split gera pedaços, tendo registros separados por caracteres nulos, um registro por pedaço. Em vez de gravar em arquivos, split chama um filtro para cada parte separadamente:
    1. primeiro tr exclui caracteres nulos;
    2. , em seguida, read e printf apenas ecoam a primeira linha (cabeçalho) do bloco;
    3. finalmente sort faz seu trabalho com as linhas restantes.
  3. Os pedaços são processados sequencialmente; a saída é um único fluxo concatenado.
por 04.06.2018 / 14:49