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.
sed
me 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 sed
para 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
, ksh
e bash
versão até 5.0 que implementa aqui documentos com arquivos temporários (em oposição a pipes como dash
ou yash
(ou bash
5.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/stdin
não significastdinda mesma forma -
. Em vez disso, é um link simbólico para o arquivo aberto no stdin, portanto, cada vez que sed
o 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 conf
arquivos suficientes que sed
sejam chamados apenas uma vez. Quando chamado pela segunda vez, em sistemas não Linux/Cygwin, como with -f -
, /dev/stdin
apareceria vazio porque já foi lido pela primeira invocação.
busybox
sed
também suporta -i
da mesma forma que o GNU sed
, mas não suporta -f -
. Então você gostaria de usar -f /dev/stdin
lá 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 ed
para procurar FILENAME
uma linha contendo a string BASE64
, inserir o conteúdo base64.txt
após essa linha, voltar para a primeira linha, procurar a linha com a string BASE64
novamente e excluí-la. O w
comando ed
salva o arquivo modificado.
Responder3
Outra opção seria substituir sed
e ed
armazenar seus comandos em um arquivo. Por exemplo, se você criar ed_cmds
com 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_64
você criaria o arquivo de comando ed.
Explicação do Ed.
%
significa aplicar o comando a cada linha do arquivos/pat1/pat2/g
substitui ocorrências depat1
withpat2
eg
no final faz isso para todas as partidas na linha, não apenas para a primeiraw
gravar as alterações no discoq
sair (o que aconteceria quando obtivesse EOF de qualquer maneira)
Claro, você poderia colocar seus sed
comandos em um arquivo e usá-los -f
também, mas se estiver fazendo isso e quiser modificar o arquivo no local, você também pode usar ed
em vez de criar um arquivo temporário e movê-lo como sed -i
faz.
Responder4
Acabei colocando as sed
instruçõ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 ed
em um arquivo, seguidas por w
e q
.