У меня есть файлы, которые заканчиваются одним или несколькими символами новой строки и должны заканчиваться только одним символом новой строки. Как я могу сделать это с помощью инструментов Bash / Unix / GNU?
Пример плохого файла:
1\n
\n
2\n
\n
\n
3\n
\n
\n
\n
Пример исправленного файла:
1\n
\n
2\n
\n
\n
3\n
Другими словами: между EOF и последним не-символом новой строки в файле должна быть ровно одна новая строка.
Реализация эталона
Прочитайте содержимое файла, отрежьте одну новую строку до тех пор, пока в конце не останется двух новых строк, запишите ее обратно:
#! /bin/python
import sys
with open(sys.argv[1]) as infile:
lines = infile.read()
while lines.endswith("\n\n"):
lines = lines[:-1]
with open(sys.argv[2], 'w') as outfile:
for line in lines:
outfile.write(line)
Пояснение: Конечно, разрешается использовать трубопроводы, если это более элегантно.
sed
предложение, я просто подумал, OMG ...awk: illegal statement
.brew install mawk
и изменение команды наmawk
работу, хотя.Из полезных однострочных скриптов для sed .
источник
find . -type f -name '*.js' -exec sed --in-place -e :a -e '/^\n*$/{$d;N;};/\n$/ba' {} \;
find . -type f -name '*.js' -exec sed -i '' -e :a -e '/^\n*$/{$d;N;};/\n$/ba' {} \;
Так как у вас уже есть ответы с более подходящими инструментами sed и awk; Вы могли бы воспользоваться тем, что
$(< file)
убирает конечные пустые строки.Этот дешевый хак не сработает для удаления конечных пустых строк, которые могут содержать пробелы или другие непечатаемые символы, только для удаления конечных пустых строк. Это также не будет работать, если файл содержит нулевые байты.
В других оболочках, кроме bash и zsh, используйте
$(cat file)
вместо$(<file)
.источник
$()
отбрасывает завершающие символы новой строки. Это дизайнерское решение. Я предполагаю, что это облегчит интеграцию в другие строки:echo "On $(date ...) we will meet."
было бы плохо с переводом строки, который выводит почти каждая команда оболочки в конце.[[ $a == '' ]] || printf '%s\n' "$a" >"$file"
.a=$(gtac file.txt); printf '%s\n' "$a" | gtac > file.txt
Вы можете использовать этот трюк с
cat
&printf
:Например
$
Обозначает конец строки.Ссылки
источник
Этот вопрос помечен как ed , но никто не предложил
ed
решение.Вот один из них:
или, что эквивалентно,
ed
по умолчанию при запуске поместит вас в последнюю строку буфера редактирования.Первая команда (
a
) добавляет пустую строку в конец буфера (пустой строкой в скрипте редактирования является эта строка, а точка (.
) предназначена только для возврата в командный режим).Вторая команда (
?
) ищет ближайшую предыдущую строку, которая содержит что-то (даже символы пробела), а затем удаляет все до конца буфера, начиная со следующей строки.Третья команда (
w
) записывает файл обратно на диск.Добавленная пустая строка защищает остальную часть файла от удаления в том случае, если в конце исходного файла нет пустых строк.
источник
Вот решение Perl, которое не требует считывания более одной строки в память одновременно:
или, как однострочник:
Это читает файл по одной строке за раз и проверяет каждую строку, чтобы увидеть, содержит ли не символ новой строки. Если это не так, он увеличивает счетчик; если это так, он печатает количество новых строк, указанных счетчиком, за которыми следует сама строка, а затем сбрасывает счетчик.
Технически, даже буферизация одной строки в памяти не нужна; можно было бы решить эту проблему, используя постоянный объем памяти, читая файл частями фиксированной длины и обрабатывая его посимвольно, используя конечный автомат. Тем не менее, я подозреваю, что это будет излишне сложно для типичного варианта использования.
источник
Если ваш файл достаточно мал, чтобы хлестать в память, вы можете использовать это
источник
В python (я знаю, что это не то, что вам нужно, но это намного лучше, поскольку оно оптимизировано, и является прелюдией к версии bash) без перезаписи файла и без чтения всего файла (что хорошо, если файл очень большой):
Обратите внимание, что он не работает с файлами, в которых символ EOL не равен \ n.
источник
Версия bash, реализующая алгоритм python, но менее эффективная, так как требует много процессов:
источник
Это быстро набрать, и, если вы знаете, sed, легко запомнить:
Он использует скрипт sed для удаления начальных пустых строк из полезных однострочных скриптов для sed , на который ссылается Alexey, выше, и tac (reverse cat).
В быстром тесте на 18-мегабайтном файле с 64 000 строк подход Алексея был более быстрым (0,036 против 0,046 секунд).
источник