Como posso consertar as linhas quebradas em lugares errados?

11

Meu arquivo de texto é assim:

This is one
sentence that is broken.
However this is a good one.
And this
one is
somehow, broken into
many.

Desejo remover o caractere de nova linha à direita de qualquer linha, seguida de uma linha começando com uma letra minúscula.

Então, isso deve ser:

This is one sentence that is broken.
However this is a good one.
And this one is somehow, broken into many.

Como posso fazer isso?

Edit: Há algumas respostas muito boas aqui, mas eu escolhi aceitar o primeiro que funcionou e foi o mais antigo. Muito obrigada a todos!

    
por user110327 26.07.2017 / 15:22

7 respostas

8

tente

awk '$NF !~ /\.$/ { printf "%s ",$0 ; next ; } {print;}' file

onde

  • $NF !~ /\.$/ linha de correspondência em que o último elemento não termina com um ponto
  • { printf "%s ",$0 imprime esta linha com um espaço de trailler e sem alimentação de linha,
  • next ; } buscar a próxima linha,
  • {print;} e imprimi-lo.

Tenho certeza de que haverá uma opção sed .

Observação: isso funcionará com a linha que termina em um ponto, no entanto, as condições nas frases que começam com letras maiúsculas não serão mescladas. Veja a resposta de Stéphane Chazelas.

    
por 26.07.2017 / 15:35
11

com awk :

awk -v ORS= '{print (NR == 1 ? "" : /^[[:lower:]]/ ? " " : RS) $0}
             END {if (NR) print RS}'

Ou seja, não anexe o separador de registro a cada linha (ORS vazio). Mas prefixar um separador de registro antes da linha atual, se não estiver na primeira linha, e a linha atual não começar com uma letra minúscula. Caso contrário, adicione um caractere de espaço, exceto na primeira linha.

    
por 26.07.2017 / 18:13
5

Em perl:

#!/usr/bin/perl -w
use strict;
my $input = join("", <>);
$input =~ s/\n([a-z])/ $1/g;
print $input;

Tecnicamente, você queria substituir "nova linha seguida por letra minúscula" por "espaço e essa letra minúscula", que é o que o núcleo do script perl acima faz:

  1. Leia na entrada uma string input .
  2. Atualize a variável input para ser o resultado da pesquisa & substitua a operação.
  3. Imprima o novo valor.
por 26.07.2017 / 15:43
5

Com sed , você pode usar um N;P;D cycle (para ter sempre duas linhas no espaço padrão e se o primeiro caractere após a nova linha estiver em minúsculas, substitua a nova linha por um espaço) e t est - assim após cada s ubstitution você reiniciar o ciclo:

sed -e :t -e '$!N;/\n[[:lower:]]/s/\n/ /;tt' -e 'P;D' infile
    
por 26.07.2017 / 15:57
4

Usando sed e fmt :

$ sed -e '1n; s/^[[:upper:]]/\n&/' input.txt | fmt
This is one sentence that is broken.

However this is a good one.

And this one is somehow, broken into many.

O script sed insere uma nova linha antes de cada linha que começa com uma letra maiúscula (exceto a primeira linha de entrada). A saída de sed é então canalizada para fmt para reformatar os parágrafos resultantes.

Como alternativa, use par se você tiver instalado. É outro reformatador de parágrafos, mas muito mais capaz do que fmt , com muitos mais recursos e opções.

Note que haverá uma linha em branco entre cada parágrafo. Os parágrafos devem ser separados uns dos outros por pelo menos uma linha em branco.  Sem as linhas em branco, toda a sua amostra de entrada é reformatada como um único parágrafo com várias frases, por exemplo:

$ fmt input.txt
This is one sentence that is broken.  However this is a good one.
And this one is somehow, broken into many.

Se você precisar remover as linhas em branco após a reformatação, direcione-as por sed novamente, mas isso removerá TODAS as linhas em branco, incluindo todas as que possam estar na entrada original. por exemplo,

$ sed -e '1n; s/^[[:upper:]]/\n&/' input.txt | fmt | sed -e '/^$/d'
This is one sentence that is broken.
However this is a good one.
And this one is somehow, broken into many.
    
por 27.07.2017 / 04:36
4

Outra maneira de fazer isso é:

perl -lpe '$\ = /\.$/ ? $/ : $"' data

em que: $\ = > ORS , $/ = > IRS = \n , $" = space

perl -pe '$_ .= <>, eof or redo if s/[^.]\K\n/ /' data

sed -e '
   :a
      /\.$/!N
      s/\n/ /
   ta
' data
    
por 26.07.2017 / 16:14
3

Python 3

import re
print(re.sub(r'\n([a-z])', r' ', open('file.txt').read(), flags=re.MULTILINE))

Esta é a mesma regex / substituição que a resposta de Jeff

    
por 26.07.2017 / 23:11