Concatena Várias linhas em uma única linha até que um padrão seja encontrado

1

Com padrões AWK e SED, acabei com um arquivo semelhante a

|
9000
3000
1000
0000
0000
2000
1000
2000
|
5669000
518000
3000
16000
0000
28000
2241000
2841000
|
9020000
453000
520000
4000
2852000
5191000
75000
|

É possível concatenar as linhas separadas entre as "|" em uma única linha separada por vírgulas?

9000,3000,1000,0000,0000,2000,1000,2000
5669000,518000,3000,16000,0000,28000,2241000,2841000
9020000,453000,520000,4000,2852000,5191000,75000

eu usei colar para fazer isso, mas produz resultados indesejados, já que o número de linhas entre o "|" não é igual.

    
por Maran Ganesh 17.08.2018 / 23:23

5 respostas

3

awk solution. Suspeito que seja um pouco prolixo.

$ awk 'BEGIN{RS="|"}NF>1{print substr(gensub(/\n/,",","g"),2,length($0)-2)}' file
9000,3000,1000,0000,0000,2000,1000,2000
5669000,518000,3000,16000,0000,28000,2241000,2841000
9020000,453000,520000,4000,2852000,5191000,75000
$

Experimente online!

    
por 17.08.2018 / 23:33
2

Isso parece funcionar bem:

$ tr "|\n" "\n," < input | sed 's/^,//;s/,$//'
9000,3000,1000,0000,0000,2000,1000,2000
5669000,518000,3000,16000,0000,28000,2241000,2841000
9020000,453000,520000,4000,2852000,5191000,75000

Usamos tr para traduzir | s em novas linhas e novas linhas em , s. Em seguida, pegamos a saída resultante e descascamos e levamos ou perdemos , s com sed .

    
por 17.08.2018 / 23:30
1
sed ':L; ${s/\n/,/g; s/,|,/\n/g; s/|,\|,|//g};  N; bL;' file
    
por 18.08.2018 / 00:09
1

Uma maneira de fazer isso pode ser:

perl -nF'\|\n' -a0777e 'print s/\n(?!\z)/,/gr for @F' input.file

Explicação:

  • Slurp o arquivo -0777 e depois divida-o em -F\|\n , ou seja, sempre que virmos um caractere de pipe seguido por um caractere de nova linha.
  • A opção -a armazenará os campos de divisão na matriz @F , que é indexada com zero.
  • O primeiro elemento da matriz @F , por exemplo, $F[0] estaria vazio, por isso não apareceria quando fosse impresso.
  • O loop for faz um loop sobre todos os elementos da matriz @F e, para cada elemento, altera todas as novas linhas que não vêem um fim de cadeia à direita imediata, (?!\z) , são substituídas por uma vírgula.

Saída:

9000,3000,1000,0000,0000,2000,1000,2000
5669000,518000,3000,16000,0000,28000,2241000,2841000
9020000,453000,520000,4000,2852000,5191000,75000

Outro método usando o editor POSIX ly sed . Aqui, carregamos o espaço padrão tanto quanto é necessário para chegar à decisão de imprimi-lo:

sed -e '
    /|$/!ba
    1d;s/\n|$//
    :b;y/\n/,/;b
    :a;$bb
    N;H;s/.*//;x;D
' input.file

Neste método, nós fazemos o slurp do arquivo:

sed -e '
    $!{                 ;# provided we"re not at the eof
        N;H;s/.*//;x;D  ;# we stick the next line to the PS & keep doing it till we hit the eof.
    }

    ;# here we have the whole file loaded into the pattern space, PS
    s/^|\n//;s/\n|$//   ;# take away the leading and trailing pipes
    s/\n|\n/,/g         ;# the internal pipes are changed to commas
    y/\n,/,\n/          ;# interchange the newlines <=> commas
' input.file

Com GNU sed , isso pode ser feito configurando um loop do-until para carregar o espaço de padrão enquanto ainda não vimos o |. Nota: com isso, estamos assumindo que as últimas e primeiras linhas da entrada são necessariamente |.

sed -e '
    1d
    :loop
        $!N
        s/\n|//
    Tloop
    y/\n/,/
' input.file
    
por 18.08.2018 / 05:59
1
awk -vRS='|' -vOFS=, '$1=$1""' infile
  • O RS='|' , altera o eperador R R ecord S , que \n ewline para um canal | .
  • O OFS=, , altera o eperador O utput F do ield S que é um espaço para uma vírgula , em vez disso.

  • O $1==$1 (você pode usar qualquer campo) causa a reavaliação de $0 (linha inteira conhecida no awk) e unirá os campos com base no RS como | e OFS como , .

  • As aspas duplas em '$1=$1""' são usadas para forçar o awk a atribuição de string, portanto, uma linha com apenas zero (s) não será excluída.

  • A saída é:

    9000,3000,1000,0000,0000,2000,1000,2000
    5669000,518000,3000,16000,0000,28000,2241000,2841000
    9020000,453000,520000,4000,2852000,5191000,75000
    
por 18.08.2018 / 10:36