Подтвердить что ты не робот

Добавить новую строку только в том случае, если она не существует

Я хочу добавить новую строку в конце файла только в том случае, если она не существует, это значит, что в конце файла несколько строк новой строки.

Я надеюсь использовать sed. Здесь проблемы, которые возникают у меня с моим текущим кодом:

sed -i -e '/^$/d;$G' /inputfile

echo file1
name1
name2

echo file2
name3
name4
(newline)

когда я запускаю свой код в файлы;

echo file1
name1
name2
(newline)

echo file2
name3
name4

он добавляет новую строку, если она не имеет, но удаляет, если она существует... это меня озадачивает..

4b9b3361

Ответ 1

Так как он удаляет новую строку, если она не существует, вы можете просто использовать:

echo "" >> file;  sed -ie '/^$/d;$G' file; sed -ie '/^$/d;$G' file

Добавляет новую строку и удаляет все, а затем добавляет новую строку. Не изящный способ, но, безусловно, работает:)

Ответ 2

СЕПГ

GNU:

sed -i '$a\' *.txt

OS X:

sed -i '' '$a\' *.txt

$ обращается к последней строке. a\ - это функция добавления.

OS X sed

sed -i '' -n p *.txt

-n отключает печать, а p печатает пространство шаблонов. p добавляет недостающую новую строку в OS X sed, но не в GNU sed, поэтому это не работает с GNU sed.

AWK

awk 1

1 можно заменить на все, что соответствует true. Изменение файла на месте:

{ rm file;awk 1 >file; }<file

bash

[[ $(tail -c1 file) && -f file ]]&&echo ''>>file

Трейлинг новых строк удаляется из результата подстановки команды, поэтому $(tail -c1 file) пуст, только если file заканчивается линией перевода или пуст. -f file является ложным, если file пусто. [[ $x ]] эквивалентно [[ -n $x ]] в bash.

Ответ 3

Вместо того, чтобы обрабатывать весь файл, просто добавьте новую строку в конец, просто проверьте последний символ, и если это не новая строка, добавьте его. Тестирование для новой строки немного интересно, так как оболочка обычно обрезает их с конца строк, поэтому я добавляю "x" для ее защиты:

if [ "$(tail -c1 "$inputfile"; echo x)" != $'\nx' ]; then
    echo "" >>"$inputfile"
fi

Обратите внимание, что это добавит новую строку в пустые файлы, которые могут быть не такими, какие вы хотите. Если вы хотите оставить только пустые файлы, добавьте еще один тест:

if [ -s "$inputfile" ] && [ "$(tail -c1 "$inputfile"; echo x)" != $'\nx' ]; then
    echo "" >>"$inputfile"
fi

Ответ 4

Использование awk:

awk '/^$/{f=1}END{ if (!f) {print "\r"}}1' inputfile

Сопоставьте пустую строку ^$ (как и вы) и установите флаг. Если флаг не установлен в конце, поместите символ новой строки.

Примечание: \r находится в OS X. Используйте \n для других.

Ответ 5

tail -c1 file | read -r _ || echo >> file

получает последний символ файла, который передает его в read, который выйдет с ненулевым кодом выхода, если он встретит EOF перед новой строкой (так что, если последний символ файла не является новой строкой). Если read выходит отличным от нуля, добавьте новую строку в файл с помощью echo (если read завершает 0, что удовлетворяет ||, поэтому команда echo не запускается).

От http://backreference.org/2010/05/23/sanitizing-files-with-no-trailing-newline/.

Ответ 6

Я решил эту задачу, используя dos2unix (или аналоги) с флагом --newline. Преимущество заключается в том, что эти инструменты сами определяют двоичные файлы. Мне нравится решение с tail -c1, но фильтрация двоичных файлов заблаговременно для меня была очень медленной.

dos2unix --newline my_file.txt

В конце концов я написал script, который искал каталог моего проекта, преобразовал все файлы в LF (dos2unix), кроме *.cmd файлов (CRLF, unix2dos) и использовал флаг для получения строк новой строки с одним вызовом.

Ответ 7

Попробуйте использовать vi или ex:

ex -scwq foo.txt

или для нескольких файлов:

vi -es +"bufdo wq" *.txt
ex -s +"bufdo wq" *.txt

который автоматически добавляет EOL в EOF при сохранении файла, если он отсутствует.

Чтобы рекурсивно применять определенные файлы, используйте новую опцию globbing (**), например **/*.txt (enable by shopt -s globstar).

Ответ 8

Использование только Bash

Вы можете использовать подстановку команд (удалить завершающие символы новой строки) с Here Strings (добавляет новую строку):

   Command Substitution
       Command substitution allows the output of a command to replace the command  name.   There  are  two
       forms:

          $(command)
       or
          'command'

       Bash  performs  the expansion by executing command in a subshell environment and replacing the com-
       mand substitution with the standard output of the command,  with  any  trailing  newlines  deleted.
       Embedded newlines are not deleted, but they may be removed during word splitting.  The command sub-
       stitution $(cat file) can be replaced by the equivalent but faster $(< file).



   Here Strings
       A variant of here documents, the format is:

          [n]<<<word

       The word undergoes brace expansion, tilde expansion, parameter and variable expansion, command sub-
       stitution,  arithmetic expansion, and quote removal.  Pathname expansion and word splitting are not
       performed.  The result is supplied as a single string, with a newline appended, to the  command  on
       its standard input (or file descriptor n if n is specified).

Вот как это работает:

cat <<<"$(<inputfile)"

Вывод в файл:

cat <<<"$(<inputfile)" >outputfile

Если вам нужно, чтобы inputfile и outputfile inputfile и то же имя файла, у вас есть пара опций - используйте команду sponge, сохраните во временную переменную с большей подстановкой команд или сохраните во временный файл.


Используя Sed

Другие предложили использовать

sed '$a\' inputfile

который ничего не добавляет к последней строке. Это нормально, но я думаю

sed '$q' inputfile

немного понятнее, потому что выходит на последней строке. Или вы можете сделать

sed -n 'p'

который использует -n для подавления вывода, но выводит его обратно с помощью p.

В любом из этих случаев sed исправит строку и добавит новую строку, по крайней мере для GNU и BSD sed. Тем не менее, я не уверен, что эта функциональность определяется POSIX. Версия sed может просто пропустить вашу строку без новой строки, поскольку строка определяется как

Последовательность из нуля или более символов non- плюс завершающий символ.