Como colocar frases em linhas separadas no Linux

7

Eu tenho uma tarefa para colocar frases em um arquivo de texto em linhas separadas. Algo assim quase funciona:

cat file.txt | tr '.' '\n'

Mas eu não quero perder pontos, pontos de interrogação e pontos de exclamação de minhas frases. Como posso fazer isso funcionar?

    
por Anu 18.03.2015 / 15:16

7 respostas

17

Não posso ter certeza sem ver um exemplo real de seus dados, mas o que você provavelmente está procurando é adicionar uma nova linha após cada ocorrência de . , ! e ? . Eu não sei como você quer lidar com ponto e vírgula ( ; ) já que eles não estão realmente marcando o fim de uma frase. Isso é contigo.

De qualquer forma, você pode tentar sed :

$ echo 'This is a sentence! And so is this. And this one?' | 
    sed 's/[.!?]  */&\n/g' 
This is a sentence! 
And so is this. 
And this one?

O s/// é o operador de substituição. Seu formato geral é s/pat/replacement e substituirá pat por replacement . O g no final faz com que seja executada a substituição em todas as ocorrências de pat . Sem isso, pararia no primeiro. O & é uma construção sed especial que significa "o que foi correspondido". Então, aqui estamos substituindo qualquer . , ! ou ? pelo que foi correspondido e uma nova linha.

Se o seu texto puder incluir abreviações como e.g. , talvez você queira substituir somente se a próxima letra for um CAPITAL:

$ echo 'This is a sentence! And so is this. And this one? Negative, i.e. no.' | sed 's/\([.!?]\) \([[:upper:]]\)/\n/g' 
This is a sentence!
And so is this.
And this one?
Negative, i.e. no.

Observe que isso não lidará com sentenças como Dr. Jones said hello. corretamente, pois assumirá que . após Dr define uma sentença, já que a próxima letra é colocada em maiúscula. No entanto, estamos agora nos aproximando de um nível de complexidade muito além do formato Q & A simples e, na verdade, requer um analisador de linguagem natural completo.

    
por 18.03.2015 / 15:24
6

Tente:

sed -e :1 -e 's/\([.?!]\)[[:blank:]]\{1,\}\([^[:blank:]]\)/\
/;t1'

Em uma entrada como:

Sentence 1. Sentence 1.2? Sentence 2!? Sentence 3.
Sentence 4... Sentence 5.

Dá:

Sentence 1.
Sentence 1.2?
Sentence 2!?
Sentence 3.
Sentence 4...
Sentence 5.

(e é POSIX).

    
por 18.03.2015 / 15:53
2

Use sed :

sed 's/\./\.\n/' file.txt
    
por 18.03.2015 / 15:23
2

A tarefa tem algumas armadilhas. Uma opção poderia ser:

sed 's/\([.?!;]\) */\n/g' file.txt

Isso substitui os caracteres no conjunto de caracteres fornecido ( [.?!;] , adiciona dois pontos ou remove o ponto-e-vírgula conforme necessário) seguido por espaços em branco opcionais ( * ) pelo caractere substituído ( expande para o caractere correspondência entre \( e \) ) e uma nova linha ( \n ).

    
por 18.03.2015 / 15:27
1

Tente:

awk -F. '{ for (i=1;i<=NF;i++) printf "%s.\n",$i ;} ' < input_file > output_file

onde

  • o awk usa . (ponto) como separador,
  • e faz um loop para cada campo, imprimindo a linha, um ponto e uma nova linha
por 18.03.2015 / 18:18
1

Existe vida fora dos limites ...

Os separadores de frases nunca estão prontos, há sempre mais um detalhe para corrigir: um Perl multiliner!

#!/usr/bin/perl

use strict;
my $pont=qr{[.!?]+};                   ## pontuation
my $abrev=qr{\b(?:Pr|Dr|Mr|[A-Z])\.};  ## abreviations

$/="";   

while(<>){ chomp;                      ## for each paragraph,

  s/\h*\n\h*/ /g;                      ## remove \n
  s/($pont)\h+(\S)/$1\n$2/g;           ## pontuation+space
  s/($abrev)\n/$1 /g;                  ## undo \n after abreviations

  print "$_\n\n";
}

com:

A single ‘-’ operand is not really an option ! It stands for
standard input. Or for standard output ? For example:
‘smth -’ reads from stdin; and is equal
to plain ‘smth’... Could it appear as any operand that
requires a file name ? Certainly !

Robert L. Stevenson wrote  Dr. Jekyll and Mr. Hyde. Back in 12.12.1886

the end

a saída é:

A single ‘-’ operand is not really an option !
It stands for standard input.
Or for standard output ?
For example: ‘smth -’ reads from stdin; and is equal to plain ‘smth’...
Could it appear as any operand that requires a file name ?
Certainly !

Robert L. Stevenson wrote  Dr. Jekyll and Mr. Hyde.
Back in 12.12.1886

the end
    
por 18.03.2015 / 19:53
-1
sed 's/\([.!?]  *\)\{0,1\}/\/g' <infile | xargs printf %s\n

Eu tinha essa coisa w / fold antes - que era rápido - mas percebi que poderia fazer o mesmo com xargs w / out tendo que pré-processar a entrada ou implementar qualquer sed ramificações se eu apenas escapou de todas as partes que não foi um caractere de terminação ou qualquer espaço subseqüente.

Portanto, na declaração acima, sed corresponderá à sequência nula ou a uma sequência de terminação para cada caractere (não na sequência) que ocorre na entrada. No lado direito, sed substitui a sequência nula ou a sequência de terminação em e depois insere uma barra invertida. O resultado é que cada caractere, exceto um de .!? , quando seguido por pelo menos um espaço, recebe \ escape com escape invertido. Isso inclui o \n ewline que sed insere após cada substituição ao gravar no stdout.

Como xargs elidirá inteiramente um \n ewline com escape de contrabarra e dividirá os argumentos que entrega seu utilitário nomeado em espaços sem escape, printf exibe todas as cadeias semelhantes a sentenças que xargs lê na entrada sans quaisquer espaços à direita e em uma única linha por. O que é mais - ele faz em lotes aproximando ARGMAX tamanho - o maior número possível de cada vez. E é claro que sed deve gerenciar seu trabalho muito rapidamente - só tem que fazer a substituição global por linha de entrada.

Os resultados funcionam assim:

Algum Lorem Ipsum retirado de www.lipsum.com :

sed 's/\([.!?]  *\)\{0,1\}/\/g' <<LIPSUM | xargs printf %s\n
Section 1.10.32 of "de Finibus Bonorum et Mal
orum", written by Cicero in 45 BC
"Sed ut perspiciatis unde omnis iste natus er
ror sit voluptatem accusantium doloremque lau
dantium, totam rem aperiam, eaque ipsa quae a
b illo inventore veritatis et quasi architect
o beatae vitae dicta sunt explicabo.
Nemo enim ipsam voluptatem quia voluptas sit 
aspernatur aut odit aut fugit, sed quia conse
quuntur magni dolores eos qui ratione volupta
tem sequi nesciunt.
Neque porro quisquam est, qui dolorem ipsum q
uia dolor sit amet, consectetur, adipisci vel
it, sed quia non numquam eius modi tempora in
cidunt ut labore et dolore magnam aliquam qua
erat voluptatem.
Ut enim ad minima veniam, quis     ...
...
reiciendis voluptatibus maiores alias consequ
atur aut perferendis doloribus asperiores rep
ellat."        1914 translation by H.

LIPSUM

... que imprime ...

Section 1.10.32 of "de Finibus Bonorum et Malorum", written by Cicero in 45 BC
"Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt.
Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.
Ut enim ad minima veniam, quis     ...
...
reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat."        1914 translation by H.
    
por 19.03.2015 / 01:06