Quiero crear un script quine .sh y esto es lo que he hecho hasta ahora
quine.sh
:
#!/bin/sh
q="#!/bin/sh\nq=$q;echo \$q";echo $q
Centrarse en esta línea:
q="#!/bin/sh\nq=$q;echo \$q";echo $q
En la primera aparición de $q
(en \nq=$q
), primero quiero configurar el resto de la variable y luego esta parte (algo de línea setlocal enabledelayedexpansion
en archivos por lotes).Tenga en cuenta que quiero una solución para sh
, no bash
o algo más, ya que quiero portabilidad.. Además, no me den consejos sobre cómo acortar mi código, etc. Solo quiero una solución para el problema anterior.
Respuesta1
Si envolvemos la cadena inicial en '
s en lugar de "
s, entonces $q
no se expandirá inmediatamente. Luego podemos expandirlo más tarde usando eval
:
#!/bin/sh
q='#!/bin/sh\nq=$q;eval "echo \"\$q\""';eval "echo \"$q\""
Desafortunadamente, la \n
no se expande, la '
s y "
la s se pierden y la \"
s se convierte "
en s.
Producción:
#!/bin/sh\nq=#!/bin/sh\nq=$q;eval "echo \"\$q\"";eval echo "$q"
Estamos bastante cerca, pero intentar arreglar el escape sed
termina volviéndose bastante engorroso.
El enlace de jw013 recomienda un enfoque bastante comprensible:
- Parte 1: definir algunos datos (por ejemplo, una variable) que contiene la segunda parte del programa
- Parte 2: use los datos para generar la primera parte del programa y luego use los datos para generar la segunda parte del programa. (Aquí se necesita envolver y escapar para la parte 1).
Aquí hay un burdo intento inicial de lograrlo:
#!/bin/sh
data="echo -e \"#!/bin/sh\ndata=\"\$data\"\"\\n\$data"
echo -e "#!/bin/sh\ndata=\"$data\"\n$data"
Producción:
#!/bin/sh
data="echo -e "#!/bin/sh
data="$data""
$data"
echo -e "#!/bin/sh
data="$data""
$data
Este intento adolece de \n
ser siempre interpretado y de \
perderse. Necesitamos alguna forma de escapar de la cadena de datos cuando la imprimamos nuevamente.
Aquí hay una mejora que utiliza múltiples llamadas echo
para evitar problemas con \n
s.
#!/bin/sh
data='echo "#!/bin/sh"\necho "data=$data"\necho -e "$data"'
echo "#!/bin/sh"
echo "data='$data'"
echo -e "$data"
Tiene un pequeño defecto que es difícil de superar: faltan '
mensajes en la salida (en el medio echo
):
#!/bin/sh
data='echo "#!/bin/sh"\necho "data=$data"\necho -e "$data"'
echo "#!/bin/sh"
echo "data=$data"
echo -e "$data"
Eso es todo lo que tengo para ti. Algunos puntos de partida para escapar de los problemas. ¡Buena suerte!