Use sed para substituir o último espaço de cada linha por uma vírgula e remova todos os espaços

7

Eu tenho um arquivo .txt delimitado por espaços de duas colunas, mas a primeira coluna possui espaços (que são erros). Eu preciso convertê-lo em um csv, mas não posso simplesmente substituir todos os espaços por vírgulas.

Exemplo de entrada:

gi|118592783|ref|ZP_01550172.1|_biphenyl-2  3-diol_1    2-dioxygenase_[Stappia_aggregata_IAM_12614] 1

Saída desejada:

gi|118592783|ref|ZP_01550172.1|_biphenyl-23-diol_12-dioxygenase_[Stappia_aggregata_IAM_12614],1

Como posso usar sed (ou qualquer outra coisa) para substituir o último espaço em uma linha por uma vírgula e remover todos os espaços restantes? Isso criaria efetivamente um arquivo CSV?

    
por Zoey RW 15.06.2017 / 19:51

4 respostas

8

Algo como:

sed -r 's/(.*) /,/; s/ //g'

A primeira substituição, sendo gananciosa, cobrirá todos menos o último espaço no grupo, substituindo o último por um , . O segundo então eliminará o resto.

    
por muru 15.06.2017 / 20:01
3

Isso faria o trabalho:

sed -r "s/\s([0-9]+$)/,/" filename.txt | tr -d ' '

ou:

sed -r "s/\s([0-9]+$)/,/; s/\s//g" filename.txt

Exemplo de entrada:

gi|118592783|ref|ZP_01550172.1|_biphenyl-2 3-diol_1    2-dioxygenase_[Stappia_aggregata_IAM_12614] 1

Saída:

gi|118592783|ref|ZP_01550172.1|_biphenyl-23-diol_12-dioxygenase_[Stappia_aggregata_IAM_12614],1
    
por Ravexina 15.06.2017 / 19:58
3

Aqui está uma maneira geek - com um loop sed.

  1. se o padrão contiver apenas um único espaço, substitua-o por uma vírgula
  2. (caso contrário) substituir o primeiro espaço com nada e goto 1

que podemos escrever no GNU sed como

sed -e :1 -e '/^[^ ]* [^ ]*$/ s/ /,/' -e 's/ //; t1'

Teste:

$ echo 'gi|118592783|ref|ZP_01550172.1|_biphenyl-2  3-diol_1    2-dioxygenase_[Stappia_aggregata_IAM_12614] 1' | 
  sed -e :1 -e '/^[^ ]* [^ ]*$/ s/ /,/' -e 's/ //; t1'
gi|118592783|ref|ZP_01550172.1|_biphenyl-23-diol_12-dioxygenase_[Stappia_aggregata_IAM_12614],1
    
por steeldriver 15.06.2017 / 21:13
3

Perl

$ perl -ne 's/\s//g;s/^(.*)([[:digit:]])$/,/;print' input.txt                                                                                    
gi|118592783|ref|ZP_01550172.1|_biphenyl-23-diol_12-dioxygenase_[Stappia_aggregata_IAM_12614],1

ou menor:

perl -pe 's/\s//g;s/^(.*)([[:digit:]])$/,/' input.txt 
Efetivamente, isso é o oposto da abordagem de muru: primeiro nos livramos de todos os espaços, depois agrupamos tudo antes do último item (grupo ) e último item (grupo , dois que por acaso são dígitos). Substituímos a linha com o grupo e sendo separados por vírgula.

Observe que ([[:digit:]]) pode ser alterado em (.) para referenciar qualquer caractere, caso seja necessário (ou seja, se esperarmos que o último caractere seja de qualquer tipo) ou podemos usar ([[:graph:]]) para lidar apenas com caracteres imprimíveis

    
por Sergiy Kolodyazhnyy 15.06.2017 / 21:21