добавить текст с эхо без новой строки

15

Я хочу добавить текст в файл, как echo "abc" >>file.txt.

Но это добавить abcпосле новой строки

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

choijj
источник
2
В файле уже есть новая строка, вы просто добавляете после нее. Поэтому вам придется заменить символ новой строки из последней строки на «abc».
Ctrl-Alt-Delor
Добро пожаловать в StackExchange! Ваш вопрос хорош; было бы лучше, если бы вы указали примеры содержимого вашего файла (до добавления, что вы получаете после добавления, что вы хотите вместо этого). Я говорю это потому, что один из ответов - как добавить abcбез заключительного перевода строки, который (после прочтения вашего вопроса), похоже, не тот, который вы хотите.
Закон 29

Ответы:

19

echo "abc" >>file.txtставит новую строку после abc , а не до. Если вы в конечном итоге abcв своей собственной строке, это означает, что новая строка ранее abcуже присутствовала в file.txt.

Обратите внимание, что текстовый файл заканчивается новой строкой. В Unix строка состоит из последовательности символов, отличных от нуля или новой строки, за которой следует новая строка. 1 Поэтому любой непустой текстовый файл заканчивается символом новой строки.

Если вы хотите добавить текст в последнюю строку файла, вы не сможете это сделать >>, потому что он всегда добавляется в файл, поэтому он всегда пишет после последней новой строки. Вместо этого вам нужен инструмент, способный изменить существующий файл. Например, вы можете использовать sed :

sed '$ s/$/abc/' file.txt >file.txt.new && mv file.txt.new file.txt

В команде sed первая $означает «выполнить следующую команду только в последней строке», команда s/REGEX/REPLACEMENT/заменяет REGEX на REPLACEMENT, а регулярное выражение $совпадает в конце строки.

Linux команда sed имеет встроенную функцию для автоматизации этой последовательности создания нового файла и замены, так что вы можете сократить ее до

sed -i '$ s/$/abc/' file.txt

Это нулевой байт, который ASCII вызывает NUL, а Unicode - U + 0000. Программы обработки текста могут или не могут справиться с этим символом.
1 См. Определения текстового файла , строки и символа новой строки в разделе «Определения» главы «Основные определения» IEEE 1003.1-2008: 2016.

Жиль "ТАК - перестань быть злым"
источник
2
Ваш второй абзац подразумевает, что файл, который не заканчивается новой строкой, не является текстовым файлом? Например, если я возьму существующий текстовый файл ASCII, который заканчивается новой строкой, и добавлю один байт 0x41(ASCII 'A'), это технически больше не текстовый файл? Если это так, я бы предложил подчеркнуть этот момент, так как это своего рода неинтуитивное определение; в противном случае небольшое изменение в формулировке может помочь избежать путаницы.
Дэвид Z
2
@DavidZ: это стандартное определение текстового файла в Unixland. IIRC это даже в POSIX где-то.
Кевин
1
@Kevin Интересно, я никогда не слышал этого раньше. Ну, даже если это стандарт, я думаю, что это немного не интуитивно.
Дэвид Z
15

Я не думаю, что это возможно с помощью echoкоманды, sedвместо этого используйте следующий подход:

sed -i '$ s/$/abc/' file.txt
  • -i- изменить файл InPlace
  • $ - указать последнюю запись / строку
  • s/$/abc/- заменить конец строки $подстрокой abc(для последней записи)
RomanPerekhrest
источник
2
Обратите внимание, что «на месте» на самом деле не означает «на месте». Это означает «записать отредактированный контент во временный именованный файл рядом с существующим файлом и затем заменить его». Вы можете доказать это, посмотрев на иноды сdate >file; ls -i file; sed -i 's/201/ZZZ/' file; ls -i file
roaima
@roaima, я знаю о том, что sed изменяет номер инода.
РоманПерехрест
2
Я думал , что ты был бы, но я был обеспокоен тем , что с акцентом на INPLACE ОП ночью думаю , что можно было бы использовать , чтобы избежать двойного использования пространства на диске, например , с большим файлом.
Ройма
@roaima, ночь подумай -> может подумать ...
RomanPerekhrest
13

Предполагая, что файл еще не заканчивается новой строкой, и вы просто хотите добавить еще текст без добавления одного, вы можете использовать -nаргумент, например

echo -n "some text here" >> file.txt

Однако некоторые системы UNIX не предоставляют эту опцию; если это так, вы можете использовать printf, например,

printf %s "some text here" >> file.txt

(начальный %sаргумент - защита от дополнительного текста, содержащего %символы форматирования)

От man echo(на macOS High Sierra):

-n

Не печатайте завершающий символ новой строки. Это также может быть достигнуто путем добавления '\c'в конец строки, как это делают системы, совместимые с iBCS2. Обратите внимание, что этот параметр, а также его влияние '\c'определяются реализацией в стандарте IEEE 1003.1-2001 («POSIX.1») с поправками, внесенными Cor. 1-2002. Приложения, нацеленные на максимальную переносимость, настоятельно рекомендуется использовать printf(1)для подавления символа новой строки.

пушистый
источник
Это, очевидно , заканчивается переводом строки. echo -nне ставит перевод строки в конце abc, но abcвсе равно будет предшествовать перевод строки, чего пользователь хочет избежать.
Кусалананда
@Kusalananda Мой ответ был скорее с предположением, что ФП попытается изменить свой процесс так, чтобы фальшивка не появлялась \nв первую очередь. Чем больше вариантов, тем лучше, особенно если они не требуют перезаписи всего файла каждый раз, когда происходит изменение (которое может стать довольно медленным и запускаться за полиномиальное время, если это делается неоднократно).
пушистый
9

Если у вас есть truncateкоманда и ваш текстовый файл имеет NL в качестве последнего символа, вы можете удалить ее, а затем добавить свой текст следующим образом:

truncate --size -1 file.txt
echo "abc" >>file.txt

(Обратите внимание, что это не truncateзаботится о содержимом файла, и в этом примере просто уменьшает размер файла на один байт. Если ваш последний символ не является одиночным байтом, т.е. это многобайтовый "широкий" символ, то вы представите искажение.)

roaima
источник
5

То, что вы хотите, это добавить его в конце последней строки, так что непосредственно перед разделителем этой последней строки, то есть перед последним символом файла.

С помощью ksh93вы можете сделать:

echo abc 1<> file >#((EOF - 1))

Где 1<>находится стандартный оператор для открытия файла в режиме чтения + записи (и, что более важно, без усечения ) на stdout, и >#((...))это специфический для ksh93 оператор поиска (здесь для поиска перед последним байтом). Обратите внимание, что echoпишет, abc<newline>где aперезаписывает новую строку, которая была там, и echoдобавляет свой новый перевод строки.

zshЭквивалент:

zmodload zsh/system
{sysseek -w end -u 1 -1 && echo abc} 1<> file

Хотя для более точного эквивалента вам также нужно будет напечатать сообщение об ошибке при невозможности поиска:

zmodload zsh/system
if sysseek -w end -u 1 -1; then
  echo abc
else
  syserror -p "$0: $LINENO: seek: "
fi 1<> file
Стефан Шазелас
источник
-1

Вероятно, UUOC, но вы также можете сделать:

echo "$(cat file.txt)abc" >file.txt

Как указывает Жиль, эта команда ограничена:

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

Кроме того, будьте осторожны с catфайлами, с которыми вы не знакомы:

Вывод :

Используйте sed

jesse_b
источник
2
Это в основном работает, но не в том случае, если иногда в конце файла есть пустая строка и непосредственно перед пустой строкой. Например, файл с фиксированным числом строк, где последняя строка изначально пуста и растянута с течением времени, а следующая за последней строкой иногда может быть пустой.
Жиль "ТАК - перестань быть злым"
Должен ли я удалить это? Я определенно думаю, что Роман / ваш ответ - правильный путь, но я знаю, что лично мне нравится видеть альтернативы, и ОП действительно спрашивал echo: p
jesse_b
1
Также это помещает весь файл в командную строку
n.caillou
@ n.caillou, а? Это не будет ничего печатать в STDOUT.
jesse_b
2
Ну, ни одна из этих уязвимостей на самом деле не связана cat, но с проблемами с произвольными escape-последовательностями, отправляемыми на терминал.
ilkkachu