Я пытаюсь выполнить эту команду
sed -i -e "s/BASE_64/$BASE_64/" FILE_NAME
где $BASE_64
— это представление содержимого файла в формате base 64.
sed
выдает ошибку, так как строка слишком длинная.
Список аргументов слишком длинный
Как можно избежать этой ошибки?
решение1
Вы всегда можете сделать (раз уж вы используете GNU sed
( -i
)):
sed -i -f - FILE_NAME << EOF
s/BASE_64/$BASE_64/g
EOF
-f -
указывает sed
на необходимость чтения скрипта sed из stdin.
Если вы хотите повторно использовать один и тот же скрипт для нескольких файлов в Linux (и только в Linux) с оболочкой вроде zsh
, ksh
и bash
версией до 5.0, которая реализует here документы с временными файлами (в отличие от каналов вроде dash
или yash
(или bash
5.1+) для относительно небольших heredocs и все еще с GNU sed
, вы можете сделать следующее:
find . -name '*.conf' -exec sed -i -f /dev/stdin {} + << EOF
s/BASE_64/$BASE_64/g
EOF
В Linux (и только в Linux и Cygwin) /dev/stdin
это не означаетстандартный вводтаким же образом -
. Вместо этого это символическая ссылка на файл, открытый на stdin, поэтому каждый раз sed
при его открытии он открывает файл заново с самого начала. Приведенная выше команда будет работать нормально в других системах (в которых есть /dev/stdin
) или с оболочками, которые реализуют here-documents с каналами, но только если файлов достаточно мало, conf
что sed
вызывается только один раз. При повторном вызове в системах, отличных от Linux/Cygwin, например с -f -
, /dev/stdin
будет отображаться пустым, поскольку он уже был прочитан первым вызовом.
busybox
sed
также поддерживает -i
так же, как GNU sed
, но не поддерживает . Так что вам в любом случае -f -
следует использовать там. С FreeBSD используйте:-f /dev/stdin
sed
sed -i '' -f /dev/stdin FILE_NAME << EOF
s/BASE_64/$BASE_64/g
EOF
решение2
Сначала сохраните данные в кодировке base64 в файле с именем, например, base64.txt
.
Например:
base64 < originalfile > base64.txt
Затем:
printf '%s\n' '/BASE64/r base64.txt' 1 '/BASE64/d' w | ed FILENAME
Это используется ed
для поиска FILENAME
строки, содержащей строку BASE64
, вставки содержимого base64.txt
после этой строки, возврата к первой строке, затем BASE64
повторного поиска строки со строкой и удаления ее. w
Команда в ed
сохраняет измененный файл.
решение3
Другой вариант — заменить sed
и ed
сохранить ваши команды в файле. Например, если вы создаете ed_cmds
со следующим содержимым:
%s/BASE_64/<expanded variable>/g
w
q
вы могли бы тогда бежать
< ed_cmds ed FILE_NAME
и он внесет нужные вам изменения, поэтому вместо настройки $BASE_64
вам придется создать командный файл ed.
Эд Объяснение
%
означает применить команду к каждой строке файлаs/pat1/pat2/g
заменяет вхожденияpat1
наpat2
иg
в конце заставляет это делать для каждого совпадения в строке, а не только для первогоw
записать изменения на дискq
выйти (что в любом случае произошло бы, когда бы он достиг EOF)
Конечно, вы можете поместить свои sed
команды в файл и использовать -f
его, но если вы делаете это и хотите изменить файл на месте, вы можете использовать его ed
вместо создания временного файла и его перемещения, как sed -i
это делается.
решение4
В итоге я поместил sed
инструкции в файл
SEDCOMMANDS=`tempfile`
и позвонил
sed -f "$SEDCOMMANDS" -- "$FILE_NAME"
Это хорошо, если вы не используете sed -i
. Если вы хотите редактировать файл на месте, следуйтеhttps://unix.stackexchange.com/a/284188/149867и поместите эквивалентные ed
инструкции в файл, за которым следуют w
и q
.