Наверное, это сложное решение .
Я ищу простой оператор, такой как ">>", но для добавления.
Боюсь, этого не существует. Мне нужно сделать что-то вроде
mv myfile tmp кошка myheader tmp> мой файл
Что-нибудь умнее?
Наверное, это сложное решение .
Я ищу простой оператор, такой как ">>", но для добавления.
Боюсь, этого не существует. Мне нужно сделать что-то вроде
mv myfile tmp кошка myheader tmp> мой файл
Что-нибудь умнее?
mktemp
? Вы всегда можете очистить временный файл после этого ...Ответы:
Приведенный ниже хакер был быстрым неожиданным ответом, который сработал и получил множество положительных отзывов. Затем, когда вопрос стал более популярным и прошло больше времени, возмущенные люди начали сообщать, что это вроде как работает, но могут происходить странные вещи, или это просто не работает вообще, поэтому какое-то время яростно отвергали его. Так весело.
Решение использует точную реализацию файловых дескрипторов в вашей системе, и, поскольку реализация значительно различается в зависимости от nix, его успех полностью зависит от системы, однозначно непереносим и не следует полагаться ни на что, даже неопределенно важное.
Итак, со всем этим ответом был:
Создание другого файлового дескриптора для file (
exec 3<> yourfile
), а затем запись в this (>&3
), похоже, преодолевает дилемму чтения / записи для одного и того же файла. У меня работает с файлами 600K с awk. Однако попытка использовать тот же трюк с «кошкой» не удалась.Передача предисловия в качестве переменной в awk (
-v TEXT="$text"
) позволяет преодолеть проблему буквальных кавычек, которая не позволяет проделать этот трюк с помощью sed.источник
При этом по-прежнему используется временный файл, но, по крайней мере, он находится в одной строке:
Предоставлено : BASH: добавить текст / строки в файл
источник
-
послеcat
?echo -n "text"
yourfile
это символическая ссылка, это не будет делать то, что вы хотите.ed - стандартный редактор! http://www.gnu.org/fun/jokes/ed.msg.html
источник
0r header.file
echo -e '0a\nyour text here\n.\nw' | ed some_file
Джон Ми: ваш метод не гарантированно работает, и, вероятно, выйдет из строя, если вы добавите более 4096 байт материала (по крайней мере, то, что происходит с gnu awk, но я полагаю, что другие реализации будут иметь аналогичные ограничения). В этом случае он не только потерпит неудачу, но и войдет в бесконечный цикл, где будет читать свой собственный вывод, тем самым заставляя файл расти, пока не будет заполнено все доступное пространство.
Попробуйте сами:
(предупреждение: убить его через некоторое время, иначе он заполнит файловую систему)
Более того, редактировать файлы таким способом очень опасно, и это очень плохой совет, так как если что-то произойдет во время редактирования файла (сбой, диск заполнен), вы почти гарантированно останетесь с файлом в несогласованном состоянии.
источник
Невозможно без временного файла, но вот единственная подсказка
Вы можете использовать другие инструменты, такие как ed или perl, чтобы сделать это без временных файлов.
источник
Может быть , стоит отметить , что часто является хорошей идеей , чтобы безопасно генерировать временный файл , используя утилиту вроде Mktemp , по крайней мере , если сценарий когда - либо будет выполняться с привилегиями суперпользователя. Например, вы можете сделать следующее (снова в bash):
источник
Если вам это нужно на компьютерах, которыми вы управляете, установите пакет «moreutils» и используйте «sponge». Тогда вы можете сделать:
источник
{ echo "prepended text"; cat myfile } | sponge myfile
Используя bash heredoc, вы можете избежать необходимости в файле tmp:
Это работает, потому что $ (cat myfile) оценивается при оценке сценария bash перед выполнением cat с перенаправлением.
источник
предполагая, что файл, который вы хотите отредактировать, - это my.txt
И файл, который вы хотите добавить, - это заголовок
Убедитесь, что в заголовочном файле есть последняя пустая строка.
Теперь вы можете добавить к нему
В итоге вы получите
Насколько я знаю, это работает только в bash.
источник
this is the header
в my.txt осталось две строки . Даже после того, как я обновил Bash,4.3.42(1)-release
я получил тот же результат.<(...)
) , поэтому нет гарантии, что оноmy.txt
будет прочитано полностью заранее , без чего этот метод не будет работать.Когда вы начинаете пытаться делать вещи, которые становятся сложными в сценарии оболочки, я настоятельно рекомендую переписать сценарий на «правильном» языке сценариев (Python / Perl / Ruby / и т. Д.)
Что касается добавления строки к файлу, это невозможно сделать через конвейер, поскольку, когда вы делаете что-либо подобное
cat blah.txt | grep something > blah.txt
, он непреднамеренно очищает файл. Есть небольшая служебная команда, которуюsponge
вы можете установить (вы делаетеcat blah.txt | grep something | sponge blah.txt
и она буферизует содержимое файла, а затем записывает его в файл). Он похож на временный файл, но вам не нужно делать это явно. но я бы сказал, что это «худшее» требование, чем, скажем, Perl.Может быть способ сделать это через awk или аналогичный, но если вам нужно использовать shell-скрипт, я думаю, что временный файл - это, безусловно, самый простой (только /?) Способ ..
источник
Как предлагает Даниэль Велков, используйте тройник.
Для меня это простое умное решение:
источник
РЕДАКТИРОВАТЬ: это сломано. См. Странное поведение при добавлении к файлу с помощью cat и tee
Решение проблемы перезаписи
tee
:источник
Тот, который я использую. Это позволяет вам указывать порядок, дополнительные символы и т. Д. Так, как вам нравится:
PS: только он не работает, если файлы содержат текст с обратной косой чертой, потому что он интерпретируется как escape-символы
источник
В основном для удовольствия / гольфа, но
сделает свое дело, и нет конвейеров или перенаправлений. Конечно, vi / ex на самом деле не для неинтерактивного использования, поэтому vi кратковременно вспыхнет.
источник
Почему бы просто не использовать команду ed (как уже было предложено здесь fluffle)?
ed считывает весь файл в память и автоматически выполняет редактирование файла на месте!
Итак, если ваш файл не такой уж большой ...
Еще один обходной путь - использовать дескрипторы открытых файлов, как предложил Юрген Хётцель в выводе Redirect из sed 's / c / d /' myFile в myFile.
Все это, конечно, можно было бы записать в одну строчку.
источник
Вариант решения cb0 для "без временного файла" для добавления фиксированного текста:
Опять же, это зависит от выполнения суб-оболочки - (..) - чтобы кот не отказался иметь один и тот же файл для ввода и вывода.
Примечание: понравилось это решение. Однако на моем Mac исходный файл потерян (думал, что не должен, но это так). Это можно исправить, написав свое решение как: echo "текст для добавления" | кошка - file_to_be_modified | cat> tmp_file; mv tmp_file file_to_be_modified
источник
Вот что я обнаружил:
источник
источник
ВНИМАНИЕ: для удовлетворения потребностей OP требуется немного больше работы.
Должен быть способ заставить работать sed с помощью @shixilun, несмотря на его опасения. Должна быть команда bash для экранирования пробелов при чтении файла в заменяющую строку sed (например, заменять символы новой строки на '\ n'. Команды оболочки
vis
иcat
могут работать с непечатаемыми символами, но не с пробелами, поэтому это не решит OP проблема:не выполняется из-за необработанных символов новой строки в сценарии замены, которые должны быть добавлены с символом продолжения строки () и, возможно, за ним следует &, чтобы оболочка и sed были счастливы, как этот ответ SO
sed
имеет ограничение по размеру 40 КБ для неглобальных команд поиска-замены (без завершающего символа / g после шаблона), поэтому, вероятно, можно избежать пугающих проблем с переполнением буфера awk, о которых предупреждал аноним.источник
источник
С помощью $ (command) вы можете записать вывод команды в переменную. Поэтому я сделал это тремя командами в одной строке и без временного файла.
источник
Если у вас есть большой файл (несколько сотен килобайт в моем случае) и доступ к python, это намного быстрее, чем
cat
решения pipe:python -c 'f = "filename"; t = open(f).read(); open(f, "w").write("text to prepend " + t)'
источник
Решение с
printf
:Вы также можете сделать:
Но в этом случае вы должны быть уверены, что ничего нет
%
, включая содержимое целевого файла, так как это может быть интерпретировано и испортить ваши результаты.источник
echo
кажется более безопасным вариантом.echo "my new line\n$(cat my/file.txt)" > my/file.txt
${new_line}
, а не о целевом файлеВы можете использовать командную строку perl:
Где -i создаст встроенную замену файла, а -0777 проглотит весь файл и заставит ^ соответствовать только началу. -pe напечатает все строки
Или, если my_header - это файл:
Где / e разрешает оценку кода при замене.
источник
где «my_file» - это файл, к которому нужно добавить «my_string».
источник
Я любя @ fluffle в ред подхода к лучшему. В конце концов, переключатели командной строки любого инструмента и команды редактора сценариев здесь по сути одно и то же; не видя, что "чистота" решения для редактора сценариев становится меньше или еще много чего.
Вот мой однострочник, добавленный к добавлению файла в
.git/hooks/prepare-commit-msg
репо.gitmessage
для фиксации сообщений:Пример
.gitmessage
:Я делаю это
1r
вместо0r
, потому что это оставит пустую строку, готовую к записи, поверх файла из исходного шаблона. Не помещайте пустую строку поверх слова.gitmessage
then, в результате вы получите две пустые строки.-s
подавляет вывод диагностической информации изд.В связи с этим я обнаружил, что для vim-buffs также хорошо иметь:
источник
переменные, ftw?
источник
Думаю, это самый чистый вариант ed:
как функция:
источник
Если вы пишете скрипт на BASH, вы можете просто ввести:
Это на самом деле в сложном примере, который вы сами опубликовали в своем собственном вопросе.
источник
cat - yourfile <<<"text" > /tmp/out && mv /tmp/out yourfile
, однако это существенно отличается от моего ответа, и это должен быть собственный ответ.ИМХО нет (и никогда не будет) оболочки, которая работала бы последовательно и надежно независимо от размеров двух файлов
myheader
и файловmyfile
. Причина в том, что если вы хотите сделать это, не возвращаясь к временному файлу (и не позволяя оболочке молча возвращаться к временному файлу, например, через такие конструкции, какexec 3<>myfile
, трубопровод кtee
и т. Д.«Настоящее» решение, которое вы ищете, должно возиться с файловой системой, поэтому оно недоступно в пользовательском пространстве и будет зависеть от платформы: вы просите изменить указатель файловой системы, который используется,
myfile
на текущее значение указателя файловой системы. formyheader
и замените в файловой системеEOF
ofmyheader
на связанную ссылку на текущий адрес файловой системы, на который указываетmyfile
. Это нетривиально и, очевидно, не может быть сделано не суперпользователем, и, вероятно, не суперпользователем ... Играйте с inode и т. Д.Однако вы можете более или менее подделать это с помощью петлевых устройств. См., Например, эту тему SO .
источник