Substitua a string que contém a nova linha em um arquivo enorme

Substitua a string que contém a nova linha em um arquivo enorme

Alguém conhece uma ferramenta não baseada em linha para pesquisar/substituir strings "binárias" de maneira um tanto eficiente em termos de memória?Veressa questãotambém.

Eu tenho um arquivo de texto de + 2 GB que gostaria de processar de maneira semelhante ao que parece fazer:

sed -e 's/>\n/>/g'

Isso significa que quero remover todas as novas linhas que ocorrem após a >, mas não em qualquer outro lugar, então isso exclui tr -d.

Este comando (que eu recebi dea resposta de uma pergunta semelhante) falha com couldn't re-allocate memory:

sed --unbuffered ':a;N;$!ba;s/>\n/>/g'

Então, existem outros métodos sem recorrer a C? Eu odeio perl, mas estou disposto a abrir uma exceção neste caso :-)

Não tenho certeza de nenhum caractere que não ocorra nos dados, portanto, a substituição temporária \npor outro caractere é algo que gostaria de evitar, se possível.

Alguma boa ideia, alguém?

Responder1

Isso é realmente trivial em Perl, você não deveria odiar isso!

perl -i.bak -pe 's/>\n/>/' file

Explicação

  • -i: edite o arquivo no local e crie um backup do original chamado file.bak. Se você não quiser um backup, basta usar perl -i -pe.
  • -pe: leia o arquivo de entrada linha por linha e imprima cada linha após aplicar o script fornecido como -e.
  • s/>\n/>/: a substituição, assim como sed.

E aqui está uma awkabordagem:

awk  '{if(/>$/){printf "%s",$0}else{print}}' file2 

Responder2

Uma perlsolução:

$ perl -pe 's/(?<=>)\n//'

Explicação

  • s///é usado para substituição de string.
  • (?<=>)é o padrão lookbehind.
  • \ncorresponde à nova linha.

Todo o padrão significa remover todas as novas linhas anteriores >.

Responder3

Que tal agora:

sed ':loop
  />$/ { N
    s/\n//
    b loop
  }' file

Para GNU sed, você também pode tentar adicionar a opção -u( --unbuffered) conforme a pergunta. GNU sed também está satisfeito com isso como uma simples linha:

sed ':loop />$/ { N; s/\n//; b loop }' file

Responder4

sednão fornece uma maneira de emitir saída sem uma nova linha final. Sua abordagem using Nfunciona fundamentalmente, mas armazena linhas incompletas na memória e, portanto, pode falhar se as linhas se tornarem muito longas (as implementações sed normalmente não são projetadas para lidar com linhas extremamente longas).

Você pode usar o awk.

awk '{if (/<$/) printf "%s", $0; else print}'

Uma abordagem alternativa é trocar tro caractere de nova linha por um caractere “chato” e de ocorrência frequente. O espaço pode funcionar aqui – escolha um caractere que tende a aparecer em todas as linhas ou pelo menos em uma grande proporção de linhas em seus dados.

tr ' \n' '\n ' | sed 's/> />/g' | tr '\n ' ' \n'

informação relacionada