Замена длинной строки с помощью команды sed: Argument list too long error

У меня тоже сработало это решение. Но поскольку моей оболочкой по умолчанию является TCSH, мне пришлось немного отредактировать исправление следующим образом (в .tcshrc):

if ( $?SSH_TTY ) then
    exec /bin/bash
endif

Просто подумал, что поделюсь им для всеобщего блага.

7
19.05.2016, 16:15
5 ответов

Сначала сохраните данные в кодировке 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 сохраняет измененный файл.

7
27.01.2020, 20:15

Размер представления файла в формате Base64 ($ BASE_64) слишком длинный и превышает максимальный размер аргумента. Вы должны увидеть этот предел для своей системы, запустив

getconf ARG_MAX

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

2
27.01.2020, 20:15

Другой вариант - заменить 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.

4
27.01.2020, 20:15

Вы всегда можете сделать (поскольку вы уже используете 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
8
27.01.2020, 20:15

В итоге я поместил инструкции sed в файл

SEDCOMMANDS=`tempfile`

и вызвал

sed -f "$SEDCOMMANDS" -- "$FILE_NAME"

. Это хорошо, если вы не используете sed -i . Если вы хотите отредактировать файл на месте, следуйте https://unix.stackexchange.com/a/284188/149867 и поместите в файл эквивалентные инструкции ed , а затем w и q .

2
27.01.2020, 20:15

Теги

Похожие вопросы