Как я могу удалить последний разделитель запятых в конце файла?

9

Как удалить последний запятую из файла в Linux?

Пример файла:

"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",

Ожидаемые результаты:

"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"
Яэль
источник

Ответы:

22

Используя GNU sed:

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

То есть в последней строке ( $) подставьте ( s) запятую в конце строки ( ,$) ничем.

Изменение будет сделано на месте из-за -iфлага.

Со стандартом sed:

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

Примечание: кто-то предложил редактирование, чтобы изменить «в последней строке» на «последний в строке» (или что-то подобное). Это не верно. Когда $используется для указания адреса (строка, в которой нужно применить команду редактирования), тогда это относится к последней строке потока или файла. Это отличается от использования $в регулярном выражении.

Кусалананда
источник
6

Для редактирования на месте вы могли бы использовать ed- удобно, при открытии он по умолчанию устанавливает позицию последней строки, поэтому вам не нужно явно обращаться к последней строке:

ed file
s/,$//
wq

Или, как однострочник

printf 's/,$//\nwq\n' | ed -s file
steeldriver
источник
2
В bash вы можете обойтись без printfэтого: ed -s file <<< $'s/,$//\nwq\n'(ключевое слово для поиска в руководстве по bash - "здесь строка").
Руслан
5

В общем, я бы, наверное, пошел с простым sedрешением. Однако, если ваши входные файлы огромны, вам может потребоваться решение, которое не займет время, чтобы прочитать весь файл только для редактирования последней пары байтов.

Если вы на 100% уверены, что ваш входной файл оканчивается запятой, за которой следует truncateсимвол новой строки, вы можете использовать эти два последних символа, а затем повторно добавить последний символ новой строки:

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

Предполагается, что дистрибутив включает усеченный GNU или эквивалентный.


@ StéphaneChazelas указывает, что GNU truncateтеперь поддерживает truncate -s -2 fileсокращение файла на два байта ; если у вас есть эта версия, выше упрощается:

truncate --size -2 lastcomma.txt
echo >> lastcomma.txt 
Цифровая травма
источник
... и файловая система, которая поддерживаетtruncate
Malat
@malat, какая файловая система не поддерживает усечение?
Стефан Шазелас
@ StéphaneChazelas Правильно, это плохо сформулировано. Как насчет: [...] и файловой системы, которая поддерживает разреженный файл для эффективной работы truncate. ОП описывает свое решение, начиная с: «если ваши входные файлы огромны» ... отсюда мой комментарий.
Малат
2
truncateТеперь GNU поддерживает truncate -s -2 fileсокращение файла на два байта. Вы хотели бы использовать stat -Lкак для символических ссылок, вы хотите размер целевой символической ссылки (или просто size=$(wc -c < file)).
Стефан Шазелас
2
@malat, вам не нужна поддержка разреженных файлов для усечения файлов. Здесь мы обрезаем данные в конце файла.
Стефан Шазелас