Classificar pacotes de linhas alfabeticamente

3

Nota: a pergunta complementar é aqui: Como classificar separadamente linhas dentro de vários “pedaços” separados por cabeçalhos?

Então, o que eu encontrei uma resposta é como classificar as linhas em um arquivo de texto em ordem alfabética. Mas não é exatamente o que preciso fazer. Eu tenho este arquivo com perfis contendo 15 parâmetros diferentes que vão para um instrumento no trabalho e é lido pela máquina para ter uma lista de perfis.

Infelizmente, a formatação deste arquivo é assim:

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

E eu quero classificar os perfis em ordem alfabética, mas preciso que eles fiquem agrupados com seus parâmetros. O exemplo acima deve ser classificado assim:

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

Eu acho que há algo para trabalhar com o número fixo de linhas (nome + parâmetros) ou com o caractere "[" como um identificador para o início de um grupo de linhas.

Mas isso está além da minha capacidade de manipulação de texto. Tenho à minha disposição o console de comando Sublime Text, R ou Linux.

    
por Paul Giroud 01.06.2018 / 12:36

2 respostas

3

Isso funciona no meu Debian:

sed '1 ! s/^\[/\x00\[/g' | sort -z | tr -d "
sed '1 ! s/^\[/\x00\[/g' | sort -z | tr -d "%pre%"
"

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 um 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. sort -z usa esses caracteres nulos como separadores, então classifica perfis inteiros, não linhas separadas.
  3. tr exclui caracteres nulos.
por 01.06.2018 / 23:25
0

Aqui está um pequeno script em Perl que faz o trabalho:

my %profiles;
my $profile;

while (<>) {
    if (/\[(.+)\]/) {
        $profile = $1;
        next;
    }
    next if !defined $profile;

    chop if /\n$/;
    push @{ $profiles{$profile} }, $_;
}

foreach my $key (sort keys %profiles) {
    print "[$key]\n";
    foreach my $line (sort @{ $profiles{$profile} }) {
        print "$line\n";
    }
}

Salve em um arquivo, sortProfiles.pl por exemplo e execute:

perl sortProfiles.pl <inputFile.txt >outputFile.txt

Como funciona

  1. Ele lê o arquivo de entrada ( while (<>) ).
  2. Para cada perfil, [profile] no arquivo de entrada, ele lembra seu nome na variável $profile .
  3. Ele salva cada linha seguindo o cabeçalho do perfil dentro de uma matriz.
  4. Em seguida, ele classifica as chaves de %profiles hash.
  5. Também classifica as linhas dentro da matriz.

Nesse script, %profiles é um hash. Suas chaves são nomes de perfil , seus valores são matrizes de linhas .
Assim, @{ $profiles{$profile} } é a matriz que armazena linhas para o nome do perfil na variável $profile .

    
por 07.06.2018 / 23:55