Certifique-se de que há um caractere no final de cada linha

5

Eu tenho um arquivo com o seguinte conteúdo.

This
is,
are,,,
a,,

Eu quero substituir o final da linha por vírgula única. Se não houver vírgula no final da linha, adicione uma vírgula e, se houver mais de uma vírgula, substitua-a por vírgula única.

A saída

é semelhante a esta

This,
is,
are,
a,
    
por JalT 13.07.2016 / 11:10

2 respostas

19

A abordagem mais simples é usar sed com edição no local:

sed -i 's/,*$/,/' file

O -i faz as alterações no mesmo arquivo. Você pode usar i.bak para criar um arquivo de backup file.bak do original. Você também pode executá-lo sem o -i para ver as alterações antes de aplicá-las. O s/foo/bar/ é o operador de substituição. Ele substituirá a primeira instância de foo por bar . O $ marca o final da linha e * significa "0 ou mais". Portanto, s/,*$/,/ significa "substituir 0 ou mais vírgulas no final da linha por uma vírgula". Se não houver vírgulas, uma será adicionada e, se houver mais de uma, elas serão substituídas por uma única.

Algumas outras opções, para fins de conclusão:

  • Perl

    perl -i -pe  's/,*$/,/' file
    

    Mesma ideia que o sed acima. É aqui que sed obteve a idéia de -i .

    Se a velocidade é um problema, esta será a mais rápida de todas as soluções aqui:

    perl -i -lne 'printf join ",", (grep {$_ ne ""}split(/,/) ); print ","' file
    
  • awk

    awk '{sub(/,*$/,",")}1;' file >newfile
    

    Ou, com versões mais recentes do (g) awk:

    awk -iinplace '{sub(/,*$/,",")}1;' file
    
  • Concha pura (mais lenta e menos eficiente, apenas incluída como exemplo):

    while read line; do echo "${line/%,*/},"; done < file > newfile
    

    O ${var/%foo/bar} substituirá foo do final da variável var por bar . Aqui, estamos substituindo tudo depois da última vírgula, então isso não funcionará se você tiver várias vírgulas por linha, isso só funcionará no seu exemplo . As outras soluções não possuem nenhuma dessas limitações.

por terdon 13.07.2016 / 11:13
5

Caso haja vírgulas possíveis entre

Mais lento do que a opção sed em arquivos menores, mas mais rápido em arquivos maiores (testados em 10MB), é a opção python abaixo.

Além disso, se houver a possibilidade de vírgulas em outras partes das linhas, a longa linha lateral abaixo funcionará:

python3 -c "ls = open('file').read().splitlines(); [print( (',').join([s for s in l.split(',') if not s == ''])+',') for l in ls]"

ou um pouco mais curto:

python3 -c "[print( (',').join([s for s in l.split(',') if not s == ''])+',') for l in open('f').read().splitlines()]"

... onde 'file' é o caminho absoluto para o seu arquivo, entre aspas (simples!).

exemplo

em um arquivo:

something like, for example this
here, read this line, I added some commas,,,,,,,,
are, you convinced or not,
just say something, anything

... a saída é:

something like, for example this,
here, read this line, I added some commas,
are, you convinced or not,
just say something, anything,

Explicação

ls = open('file').read().splitlines()

lê o arquivo, divide-o em linhas

[s for s in l.split(',') if not s == '']

divide a linha pelo delimitador , remove as (possíveis) vírgulas do final da linha

(',').join([s for s in l.split(',') if not s == ''])+','

une as seções de divisão, adiciona uma vírgula no final.

    
por Jacob Vlijm 13.07.2016 / 15:38