Substitua uma string longa pelo comando sed: erro de lista de argumentos muito longa

Substitua uma string longa pelo comando sed: erro de lista de argumentos muito longa

Estou tentando executar este comando

sed -i -e "s/BASE_64/$BASE_64/" FILE_NAME

onde $BASE_64é uma representação de base 64 do conteúdo de um arquivo.

sedme dá um erro porque a string é muito longa.

Lista de argumentos muito longa

Como é possível evitar esse erro?

Responder1

Você sempre pode fazer (já que já está usando GNU sed( -i)):

sed -i -f - FILE_NAME << EOF
s/BASE_64/$BASE_64/g
EOF

-f -diz sedpara ler o script sed do stdin.

Se você deseja reutilizar o mesmo script para vários arquivos, no Linux (e apenas no Linux), com um shell como zsh, kshe bashversão até 5.0 que implementa aqui documentos com arquivos temporários (em oposição a pipes como dashou yash(ou bash5.1+) para heredocs relativamente pequenos e ainda com GNU sed, você poderia fazer:

find . -name '*.conf' -exec sed -i -f /dev/stdin {} + << EOF
s/BASE_64/$BASE_64/g
EOF

No Linux (e somente Linux e Cygwin), /dev/stdinnão significastdinda mesma forma -. Em vez disso, é um link simbólico para o arquivo aberto no stdin, portanto, cada vez que sedo abre, ele abre o arquivo novamente desde o início. O comando acima funcionaria bem em outros sistemas (que possuem /dev/stdin) ou com shells que implementam documentos aqui com pipes, mas somente se houver poucos confarquivos suficientes que sedsejam chamados apenas uma vez. Quando chamado pela segunda vez, em sistemas não Linux/Cygwin, como with -f -, /dev/stdinapareceria vazio porque já foi lido pela primeira invocação.

busybox sedtambém suporta -ida mesma forma que o GNU sed, mas não suporta -f -. Então você gostaria de usar -f /dev/stdinlá em qualquer caso. Com o FreeBSD sed, use:

sed -i '' -f /dev/stdin FILE_NAME << EOF
s/BASE_64/$BASE_64/g
EOF

Responder2

Primeiro, salve os dados codificados em base64 em um arquivo chamado, por exemplo, base64.txt.

Por exemplo:

base64 < originalfile > base64.txt

Então:

printf '%s\n' '/BASE64/r base64.txt' 1 '/BASE64/d' w | ed FILENAME

Isso é usado edpara procurar FILENAMEuma linha contendo a string BASE64, inserir o conteúdo base64.txtapós essa linha, voltar para a primeira linha, procurar a linha com a string BASE64novamente e excluí-la. O wcomando edsalva o arquivo modificado.

Responder3

Outra opção seria substituir sede edarmazenar seus comandos em um arquivo. Por exemplo, se você criar ed_cmdscom o seguinte conteúdo:

%s/BASE_64/<expanded variable>/g
w
q

você poderia então correr

< ed_cmds ed FILE_NAME

e faria as alterações desejadas, então, em vez de configurar, $BASE_64você criaria o arquivo de comando ed.

Explicação do Ed.

  • %significa aplicar o comando a cada linha do arquivo
  • s/pat1/pat2/gsubstitui ocorrências de pat1with pat2e gno final faz isso para todas as partidas na linha, não apenas para a primeira
  • wgravar as alterações no disco
  • qsair (o que aconteceria quando obtivesse EOF de qualquer maneira)

Claro, você poderia colocar seus sedcomandos em um arquivo e usá-los -ftambém, mas se estiver fazendo isso e quiser modificar o arquivo no local, você também pode usar edem vez de criar um arquivo temporário e movê-lo como sed -ifaz.

Responder4

Acabei colocando as sedinstruções em um arquivo

SEDCOMMANDS=`tempfile`

e ligou

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

Isso é bom se você não usar sed -i. Se você quiser editar o arquivo no local, sigahttps://unix.stackexchange.com/a/284188/149867e coloque as instruções equivalentes edem um arquivo, seguidas por we q.

informação relacionada