Como posso remover o último separador de vírgula do final de um arquivo?

9

Como remover o último separador de vírgulas de um arquivo no Linux?

Exemplo de arquivo:

"is_supported_kafka_ranger" : "true",
"kafka_log_dir" : "/var/log/kafka",
"kafka_pid_dir" : "/var/run/kafka",
"kafka_user" : "kafka",
"kafka_user_nofile_limit" : "128000",
"kafka_user_nproc_limit" : "65536",

resultados esperados:

"is_supported_kafka_ranger" : "true",
"kafka_log_dir" : "/var/log/kafka",
"kafka_pid_dir" : "/var/run/kafka",
"kafka_user" : "kafka",
"kafka_user_nofile_limit" : "128000",
"kafka_user_nproc_limit" : "65536"
yael
fonte

Respostas:

22

Usando o GNU sed:

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

Ou seja, na última linha ( $) substitua ( s) a vírgula no final da linha ( ,$) por nada.

A alteração será feita no local devido à -ibandeira.

Com padrão sed:

sed '$s/,$//' <file >file.new &&
mv file.new file

Nota: Alguém sugeriu uma edição para alterar "na última linha" para "última na linha" (ou algo semelhante). Isto está errado. Quando $é usado para especificar um endereço (uma linha onde aplicar um comando de edição), refere-se à última linha do fluxo ou arquivo. Isso é diferente de usar $em uma expressão regular.

Kusalananda
fonte
6

Para editar no local, você pode usar ed- convenientemente, ele define a posição para a última linha por padrão na abertura, para que você não precise endereçar explicitamente a última linha:

ed file
s/,$//
wq

Ou, como uma linha

printf 's/,$//\nwq\n' | ed -s file
chave de aço
fonte
2
No bash, você pode dispensar o printfseguinte: ed -s file <<< $'s/,$//\nwq\n'(a palavra-chave para pesquisa no manual do bash é "here string").
Ruslan
5

Em geral, eu provavelmente usaria a sedsolução direta . No entanto, se seus arquivos de entrada forem enormes, convém uma solução que não demore para ler todo o arquivo apenas para editar os últimos bytes.

Se você tiver 100% de certeza de que seu arquivo de entrada termina com uma vírgula seguida por uma nova linha, você pode usar truncatepara cortar esses dois últimos caracteres e, em seguida, anexar novamente uma nova linha final:

filesize=$(stat -L --format "%s" lastcomma.txt)
truncate --size $((filesize - 2)) lastcomma.txt 
echo >> lastcomma.txt 

Isso pressupõe uma distribuição que inclui GNU truncada ou equivalente.


@ StéphaneChazelas salienta que o GNU truncateagora suporta truncate -s -2 filereduzir o arquivo em dois bytes ; se você tiver esta versão, o acima será simplificado para:

truncate --size -2 lastcomma.txt
echo >> lastcomma.txt 
Trauma Digital
fonte
... e um sistema de arquivos que suportatruncate
malat
@malat, qual sistema de arquivos não suporta truncado?
Stéphane Chazelas
@ StéphaneChazelas Certo, isso é mal formulado. Que tal: [...] e um sistema de arquivos que suporta arquivos esparsos para ter uma eficiência truncate. O OP descreve sua solução começando com: "se seus arquivos de entrada são enormes" ... daí o meu comentário.
malat
2
O GNU truncateagora suporta truncate -s -2 filereduzir o arquivo em dois bytes. Você gostaria de usar stat -Lcomo links simbólicos, o tamanho do destino do link simbólico (ou simplesmente size=$(wc -c < file)).
Stéphane Chazelas
2
@malat, você não precisa de suporte a arquivos esparsos para truncar arquivos. Aqui, estamos aparando dados no final do arquivo.
Stéphane Chazelas