Recolher algumas partes repetidas de linhas sucessivas

3

Eu tenho dados no bloco de notas assim:

4480-1
4480-2
4480-3
4480-15
4581-1
4581-2
4581-3
4581-4

Podemos fazer isso usando o tipo de loop? Com sed?

Minha saída obrigatória é 4480-1&-2&-3&-15&4581-1&-2&-3&-4

    
por user73553 25.06.2014 / 12:33

6 respostas

1

Isso deve funcionar:

awk -F- '$1!=a{printf "%s", $1} {printf "-%s&", $2} {a=$1}' file | sed 's/&$/\n/g'

Saída:

4480-1&-2&-3&-15&4581-1&-2&-3&-4

Explanação:

  • O awk -F- delimiter é -
  • $1!=a{printf "%s", $1} imprime a primeira parte 4480 se não for igual à última linha processada
  • {printf "-%s&", $2} imprime a segunda parte com & no final
  • {a=$1} definir um para a linha processada
  • sed 's/&$/\n/g' remove o último caractere que é & e adiciona uma nova linha
por 25.06.2014 / 13:56
1

Eu não acho que você pode fazer isso com sed facilmente. É mais fácil com perl :

$ perl -F'-' -anle '
    $h{$F[0]} .= defined($h{$F[0]}) ? "&-".$F[1] : "-".$F[1];
    END {
        $,="&";
        print @{[map { $_.$h{$_} } sort { $a <=> $b } keys %h]}
    }
' file
4480-1&-2&-3&-15&4581-1&-2&-3&-4
    
por 25.06.2014 / 14:15
0

Provavelmente não é possível com sed. Eu estou fazendo com AWK. Eu assumo uma entrada por linha.

awk '
  BEGIN { FS="-"; ORS=""; left="" }

  {
    if(NR>1){print "&"}

    # Only print left part if it differs from previous line
    if ($1!=left) {
      print $1 "-" $2
      left=$1;
    } else {
      print "-" $2
    }
  }' inputfile.txt

Saídas 4480-1&-2&-3&-15&4581-1&-2&-3&-4

    
por 25.06.2014 / 12:44
0

Se sua entrada não for realmente classificada como na pergunta, você deve usar sort -n file primeiro.

awk '
{
    split($1, id, "-")

    if (NR > 1) {
        printf "&"
    }

    if (prefix_test[id[1]]++ == 0) {
        printf("%s", id[1])
    }

    printf("-%s", id[2])
}

END { printf "\n" }' file
    
por 25.06.2014 / 12:49
0

Deve ser sed, mas aqui está perl:

#!/usr/bin/perl

while ( ($a,$b) = split /-/,<>) { $n->{$a}->{"-$b"}++;}

@_ = map { $_,
           map { chomp; "$_&"; } reverse sort { $a <=> $b } keys $n->{$_};
     } sort { $a <=> $b } keys $n;

@_[-1] =~ s/&$//;

print @_;

Saída numericamente ordenada, não dependendo da ordem de entrada:

4480-1&-2&-3&-15&4581-1&-2&-3&-4
    
por 25.06.2014 / 13:44
0

Uma solução awk que não requer que as entradas sejam classificadas pelo prefixo

awk -F- '
    {a[$1] = !a[$1]? $1"-"$2 : a[$1]"&-"$2} 
END {asort(a); for (i in a) printf "%s&", a[i]}
' file | sed 's/&$/\n/'

Se você não precisa que a saída seja classificada, você pode omitir o asort(a)

awk -F- '
    {a[$1] = !a[$1]? $1"-"$2 : a[$1]"&-"$2} 
END {for (i in a) printf "%s&", a[i]}
' file | sed 's/&$/\n/'
    
por 25.06.2014 / 16:05