У меня тоже сработало это решение. Но поскольку моей оболочкой по умолчанию является TCSH, мне пришлось немного отредактировать исправление следующим образом (в .tcshrc):
if ( $?SSH_TTY ) then
exec /bin/bash
endif
Просто подумал, что поделюсь им для всеобщего блага.
Сначала сохраните данные в кодировке base64 в файле с именем, например, base64.txt
.
Например:
base64 < originalfile > base64.txt
Затем:
printf '%s\n' '/BASE64/r base64.txt' 1 '/BASE64/d' w | ed FILENAME
Здесь используется ed
для поиска в FILENAME
строки, содержащей строку BASE64
, вставьте содержимое of base64.txt
после этой строки вернитесь к первой строке, затем снова найдите строку со строкой BASE64
и удалите ее. Команда w
в ed
сохраняет измененный файл.
Размер представления файла в формате Base64 ($ BASE_64) слишком длинный и превышает максимальный размер аргумента. Вы должны увидеть этот предел для своей системы, запустив
getconf ARG_MAX
. Вы должны увеличить размер значения ARG_MAX
.
Но я думаю, что если файл слишком большой, вам придется использовать другой подход для этой замены. Если сценарий Python сделает это за вас, я бы тоже попробовал с ним.
Другой вариант - заменить sed
на ed
и хранить команды в файле. Например, если вы создадите ed_cmds
со следующим содержимым:
%s/BASE_64/<expanded variable>/g
w
q
вы можете запустить
< ed_cmds ed FILE_NAME
и он внесет нужные вам изменения, так что вместо установки $BASE_64
вы создадите командный файл ed.
Ed Explanation
%
означает применение команды к каждой строке файлаs/pat1/pat2/g
заменяет вхождения pat1
на pat2
, а g
в конце делает это для каждого совпадения в строке, а не только первоеw
записывать изменения на дискq
выходить (что все равно произойдет при получении EOF)Конечно, вы можете поместить свои команды sed
в файл и использовать -f
, но если вы делаете это и хотите изменить файл на месте, вы можете использовать ed
, а не создавать временный файл и перемещать его, как это делает sed -i
.
Вы всегда можете сделать (поскольку вы уже используете GNU sed
( -i
)):
sed -i -f - FILE_NAME << EOF
s/BASE_64/$BASE_64/g
EOF
-f -
указывает sed
читать сценарий sed из стандартного ввода-вывода.
Если вы хотите повторно использовать один и тот же сценарий для нескольких файлов в Linux (и только в Linux), с оболочкой типа bash
, zsh
, ksh
который реализует здесь документы с временными файлами (в отличие от каналов типа dash
или yash
) и все еще с GNU sed
, вы можете сделать:
find . -name '*.conf' -exec sed -i -f /dev/stdin {} + << EOF
s/BASE_64/$BASE_64/g
EOF
В Linux (и только для Linux), / dev / stdin
не означает stdin так же, как -
.Вместо этого это символическая ссылка на файл, открытый на стандартном вводе, поэтому каждый раз, когда sed
открывает его, он открывает файл заново с самого начала. Вышеупомянутая команда будет работать нормально в других системах (которые имеют / dev / stdin
) или с оболочками, реализующими здесь-документы с каналами, но только если имеется достаточно мало файлов conf
, которые sed
вызывается только один раз. При повторном вызове в системах, отличных от Linux, например, -f -
, / dev / stdin
будет отображаться пустым, поскольку он уже был прочитан при первом вызове.
busybox
sed
также поддерживает -i
так же, как GNU sed
, но не поддерживает -f -
. Так что вы в любом случае захотите использовать там -f / dev / stdin
. В FreeBSD sed
используйте:
sed -i '' -f /dev/stdin FILE_NAME << EOF
s/BASE_64/$BASE_64/g
EOF
В итоге я поместил инструкции sed
в файл
SEDCOMMANDS=`tempfile`
и вызвал
sed -f "$SEDCOMMANDS" -- "$FILE_NAME"
. Это хорошо, если вы не используете sed -i
. Если вы хотите отредактировать файл на месте, следуйте https://unix.stackexchange.com/a/284188/149867 и поместите в файл эквивалентные инструкции ed
, а затем w
и q
.