Como devo executar a correspondência e substituição de múltiplas linhas usando o awk?

1

Em um arquivo de texto, ignorando qualquer espaço em branco no final de cada linha, presumo que, se uma linha não for finalizada com um dígito, haverá uma quebra de linha entre a linha e a próxima linha, e eu gostaria para encontrar essas quebras de linha e, em seguida, concatená-los em uma linha. Por exemplo

line 1
li
ne 2

Há uma quebra de linha entre a segunda e a terceira linhas e eu devo modificar o arquivo para ser

line 1
line 2

Para encontrar essas quebras de linha, preciso fazer a correspondência de várias linhas. Eu faço isso alterando o separador de registro, mas o seguinte não funciona:

$ awk 'BEGIN{RS="";}; { if (match($0, /[^[:digit:] ] *\n/)) print $0;} ' inputfile

Para concatenar duas linhas separadas por uma quebra de linha, ainda estou me perguntando.

Obrigado.

    
por Tim 13.11.2018 / 17:02

4 respostas

1

Você pode executar algo nos moldes de

awk 'BEGIN{RS=SUBSEP; ORS="" } {print gensub(/([^0-9])\n/,"\1","g",$0)}' ex
  • RS=SUBSEP define o Separador de Registros como um valor que nunca está presente em um arquivo de texto (retira o arquivo de entrada para $0 )
  • então você faz uma transformação multilinha favorita
por 13.11.2018 / 18:24
4

Eu lidaria com isso de maneira diferente: fazendo o loop pela entrada até encontrar uma "condição de fim de linha":

awk '{ 
       line=$0; 
       while($0 !~ /[[:digit:]] *$/ && getline > 0) { 
         line=line$0; 
       }
       print line
     }' < input

Em um arquivo de entrada estendido de:

line 1
li
ne 2
li
ne 
number 3
line 4

Ou, mais detalhadamente (para ver o espaço à direita):

$ cat -e input
line 1$
li$
ne 2$
li$
ne $
number 3$
line 4$

A saída é:

line 1
line 2
line number 3
line 4
    
por 13.11.2018 / 17:25
2
$ cat file
line 1
li
ne 2
lo
ng li
ne 3
$ awk 'line ~ /[0-9]$/ { print line; line = "" } { line = line $0 } END { print line }' file
line 1
line 2
long line 3

Isso acumula uma "linha de saída" na variável line , e sempre que essa variável termina com um dígito, ela é impressa e redefinida. Também é impresso no final para produzir a última linha (completa ou não).

Aproximado sed equivalente (mas com um loop explícito):

$ sed -e ':again' -e '/[0-9]$/{ p; d; }; N; s/\n//' -e 'tagain' file
line 1
line 2
long line 3
    
por 13.11.2018 / 23:49
0

Pequeno GNU sed ?

sed ':L; /[0-9] *$/!{N; bL;}; s/\n//g' file
    
por 13.11.2018 / 18:25