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 \n
por 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 chamadofile.bak
. Se você não quiser um backup, basta usarperl -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 comosed
.
E aqui está uma awk
abordagem:
awk '{if(/>$/){printf "%s",$0}else{print}}' file2
Responder2
Uma perl
solução:
$ perl -pe 's/(?<=>)\n//'
Explicação
s///
é usado para substituição de string.(?<=>)
é o padrão lookbehind.\n
corresponde à 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
sed
não fornece uma maneira de emitir saída sem uma nova linha final. Sua abordagem using N
funciona 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 tr
o 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'