Combine várias linhas em um arquivo para uma única linha

1

Eu tenho um arquivo como abaixo ..

"Field1"|"Field2"|"Field3"|"ufghjkrtyrtyfgh$"  
"Field1"|"Field2  
continue on line 2  
continue on line 3"|"Field3"|"ufghjkrtyrtyfgh$"  
"Field1"|"Field2"|"Field3"|"ufghjkrtyrtyfgh$"

Estou procurando por resultados como abaixo

"Field1"|"Field2"|"Field3"|"ufghjkrtyrtyfgh$"  
"Field1"|"Field2continue on line 2continue on line "|"Field3"|"ufghjkrtyrtyfgh$"  
"Field1"|"Field2"|"Field3"|"ufghjkrtyrtyfgh$"  
  1. Cada registro terminará com $"
  2. O campo 2 pode ser distribuído por várias linhas
  3. O arquivo é delimitado por canal e aspas duplas incluídas.

Por favor, você poderia me ajudar a resolver esse problema?

    
por Viswakanth 24.05.2016 / 04:24

3 respostas

3

$ awk '/[$]"[[:space:]]*$/{print;next} {printf "%s",$0}' file
"Field1"|"Field2"|"Field3"|"ufghjkrtyrtyfgh$"
"Field1"|"Field2continue on line 2continue on line 3"|"Field3"|"ufghjkrtyrtyfgh$"
"Field1"|"Field2"|"Field3"|"ufghjkrtyrtyfgh$"

Como funciona

  • /[$]"[[:space:]]*$/{print;next}

    Para qualquer linha que termine com $ seguido por " , seguido opcionalmente por espaço em branco, isso (1) imprime a linha e (2) ignora os comandos restantes e instrui o awk a recomeçar no next de linha.

    Em expressões regulares do awk, $ significa o fim da linha. Se queremos combinar um sinal de dólar real, devemos escapar de alguma forma. A maneira mais confiável de escapar é colocar entre colchetes: [$] . Na regex acima, [$] é seguido pelo aspas duplas " e seguido por [[:space:]]* . A classe de caractere [[:space:]] corresponde a qualquer caractere de espaço em branco e o * significa que devemos corresponder a zero ou mais deles. Isso é seguido pelo $ sem escape, que corresponde ao final da linha.

  • printf "%s",$0

    Para qualquer outra linha, isso diz ao awk para imprimir a linha sem um caractere de nova linha.

por 24.05.2016 / 05:08
1
echo '"Field1a"|"Field2a"|"Field3a"|"ufghjkrtyrtyfgh$"
"Field1b"|"Field2b
continue on line 2                              
continue on line 3"|"Field3b"|"ufghjkrtyrtyfgh$"
"Field1c"|"Field2c"|"Field3c"|"ufghjkrtyrtyfgh$"' | sed -nr '/^".*"$/{p;n};:a;/[^"]$|^[^"]/{N;s/(.)\n(.)//;ta};p'
"Field1a"|"Field2a"|"Field3a"|"ufghjkrtyrtyfgh$"
"Field1b"|"Field2bcontinue on line 2continue on line 3"|"Field3b"|"ufghjkrtyrtyfgh$"
"Field1c"|"Field2c"|"Field3c"|"ufghjkrtyrtyfgh$"

Uma solução sed. Toda linha começando e terminando com "será impressa, então o comando 'n' lerá a próxima linha e iniciará um novo ciclo. Se uma linha não iniciar ou terminar com", ela irá para o loop ': a .... ta ', então o comando' N 'acrescenta a linha seguinte, o comando' s 'substitui «lastchar» «nova linha» «firstchar» (a parte' (.) \ n (.) ') por «lastchar» «firstchar» O comando 'ta' pula para a marca ': a' somente se o comando 's' realmente substitui alguma coisa (este é o loop). Se 's' não substitui nada, 'ta' não pula para a marca e sed 'penetra a linha resultante e inicia um novo ciclo com a próxima linha. A solução awk parece muito mais limpa. Acho que minha solução sed pode ser melhorada.

Editar: Opção -n suprimir saída automática de sed para imprimirmos apenas o que queremos com 'p'. opção -r é para Expressões Regulares avançadas.

    
por 25.05.2016 / 08:09
1

Uma solução de awk do GNU ligeiramente diferente:

awk -v RS='\$" *' '{gsub(" *\n", ""); print $0 RT }' file

Isso usa uma expressão regular como separador de registro.

    
por 01.06.2016 / 10:02