Estoy intentando ejecutar este comando
sed -i -e "s/BASE_64/$BASE_64/" FILE_NAME
donde $BASE_64
es una representación en base 64 del contenido de un archivo.
sed
me da error porque la cadena es demasiado larga.
Lista de argumentos demasiado larga
¿Cómo es posible evitar este error?
Respuesta1
Siempre puedes hacer (ya que sed
ya estás usando GNU ( -i
)):
sed -i -f - FILE_NAME << EOF
s/BASE_64/$BASE_64/g
EOF
-f -
le dice sed
que lea el script sed desde stdin.
Si desea reutilizar el mismo script para varios archivos, en Linux (y solo Linux), con un shell como zsh
y ksh
una bash
versión hasta 5.0 que implementa aquí documentos con archivos temporales (a diferencia de canalizaciones como dash
o yash
(o bash
5.1+) para Heredocs relativamente pequeños y aún con GNU sed
, podrías hacer:
find . -name '*.conf' -exec sed -i -f /dev/stdin {} + << EOF
s/BASE_64/$BASE_64/g
EOF
En Linux (y sólo en Linux y Cygwin), /dev/stdin
no significaentrada estándarde la misma manera -
lo hace. En cambio, es un enlace simbólico al archivo abierto en stdin, por lo que cada vez que sed
lo abre, abre el archivo nuevamente desde el principio. El comando anterior funcionaría bien en otros sistemas (que tengan /dev/stdin
) o con shells que implementen documentos aquí con canalizaciones, pero solo si hay pocos conf
archivos suficientes que sed
se llamen solo una vez. Cuando se llama por segunda vez, en sistemas que no son Linux/Cygwin, como con -f -
, /dev/stdin
aparecería vacío porque ya ha sido leído en la primera invocación.
busybox
sed
también es compatible -i
de la misma manera que GNU sed
, pero no es compatible -f -
. Entonces querrás usarlo -f /dev/stdin
allí en cualquier caso. Con FreeBSD sed
, utilice:
sed -i '' -f /dev/stdin FILE_NAME << EOF
s/BASE_64/$BASE_64/g
EOF
Respuesta2
Primero, guarde los datos codificados en base64 en un archivo llamado, por ejemplo, base64.txt
.
Por ejemplo:
base64 < originalfile > base64.txt
Entonces:
printf '%s\n' '/BASE64/r base64.txt' 1 '/BASE64/d' w | ed FILENAME
Esto se utiliza ed
para buscar FILENAME
una línea que contiene la cadena BASE64
, insertar el contenido base64.txt
después de esa línea, volver a la primera línea, luego buscar la línea con la cadena BASE64
nuevamente y eliminarla. El w
comando ed
guarda el archivo modificado.
Respuesta3
Otra opción sería reemplazar sed
y ed
almacenar sus comandos en un archivo. Por ejemplo, si crea ed_cmds
con los siguientes contenidos:
%s/BASE_64/<expanded variable>/g
w
q
entonces podrías correr
< ed_cmds ed FILE_NAME
y haría los cambios que deseaba, por lo que en lugar de configurar, $BASE_64
crearía el archivo de comando ed.
Explicación educativa
%
significa aplicar el comando a cada línea del archivos/pat1/pat2/g
sustituye las apariciones depat1
withpat2
yg
al final hace que lo haga para cada partido en la línea, no solo el primerow
escribir los cambios en el discoq
dejar de fumar (lo que sucedería cuando obtuviera EOF de todos modos)
Por supuesto, puede poner sus sed
comandos en un archivo y usarlos -f
también, pero si está haciendo eso y desea modificar el archivo en su lugar, también puede usarlo ed
en lugar de crear un archivo temporal y moverlo como lo sed -i
hace.
Respuesta4
Terminé poniendo las sed
instrucciones en un archivo.
SEDCOMMANDS=`tempfile`
y llamé
sed -f "$SEDCOMMANDS" -- "$FILE_NAME"
Eso es bueno si no lo usas sed -i
. Si desea editar el archivo en su lugar, sigahttps://unix.stackexchange.com/a/284188/149867y coloque las instrucciones equivalentes ed
en un archivo, seguidas de w
y q
.