Expansão Atrasada

Expansão Atrasada

Quero fazer um script quine .sh e foi isso que fiz até agora
quine.sh:

#!/bin/sh
q="#!/bin/sh\nq=$q;echo \$q";echo $q

Concentre-se nesta linha:

q="#!/bin/sh\nq=$q;echo \$q";echo $q

Na primeira ocorrência de $q(in \nq=$q), primeiro quero definir o resto da variável e depois esta parte (algo linha setlocal enabledelayedexpansionem arquivos em lote).Observe que quero uma solução para sh, não bashou outra coisa, pois quero portabilidade. Além disso, não me dê dicas sobre como tornar meu código mais curto, etc. Só quero uma solução para o problema acima.

Responder1

Se envolvermos a string inicial em 's em vez de "s então $qnão será expandido imediatamente. Podemos então expandi-lo mais tarde usando eval:

#!/bin/sh
q='#!/bin/sh\nq=$q;eval "echo \"\$q\""';eval "echo \"$q\""

Infelizmente o \nnão é expandido, os 's e "s são perdidos e os \"s tornam-se "s.

Saída:

#!/bin/sh\nq=#!/bin/sh\nq=$q;eval "echo \"\$q\"";eval echo "$q"

Estamos bem perto, mas tentar consertar a fuga sedacaba se tornando um tanto complicado.


O link do jw013 recomenda uma abordagem bastante compreensível:

  • Parte 1: Defina alguns dados (por exemplo, uma variável) que contém a segunda parte do programa
  • Parte 2: Use os dados para gerar a primeira parte do programa e, em seguida, use os dados para gerar a segunda parte do programa. (Manuseie o empacotamento e o escape necessários para a parte 1 aqui.)

Aqui está uma tentativa inicial grosseira disso:

#!/bin/sh
data="echo -e \"#!/bin/sh\ndata=\"\$data\"\"\\n\$data"
echo -e "#!/bin/sh\ndata=\"$data\"\n$data"

Saída:

#!/bin/sh
data="echo -e "#!/bin/sh
data="$data""
$data"
echo -e "#!/bin/sh
data="$data""
$data

Essa tentativa sofre com o fato de \nser sempre interpretada e de \se perder. Precisamos de alguma forma de escapar da string de dados quando a imprimirmos novamente.


Aqui está uma melhoria que usa múltiplas chamadas echopara evitar problemas com \ns.

#!/bin/sh
data='echo "#!/bin/sh"\necho "data=$data"\necho -e "$data"'
echo "#!/bin/sh"
echo "data='$data'"
echo -e "$data"

Ele sofre de uma pequena falha que é difícil de superar, faltando 's na saída (o meio echo):

#!/bin/sh
data='echo "#!/bin/sh"\necho "data=$data"\necho -e "$data"'
echo "#!/bin/sh"
echo "data=$data"
echo -e "$data"

Isso é tudo que tenho para você. Alguns pontos de partida para escapar de problemas. Boa sorte!

informação relacionada