Expansão atrasada

1

Eu quero fazer um script shine quine, e é isso que eu 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 (em \nq=$q ), primeiro desejo definir o restante da variável e, em seguida, essa parte (algo em linha setlocal enabledelayedexpansion em arquivos em lote). Observe que quero uma solução para sh , não bash ou outra coisa, pois desejo portabilidade . Além disso, não me dê dicas sobre como tornar meu código mais curto, etc. Eu só quero uma solução para o problema acima.

    
por EKons 12.02.2016 / 15:12

1 resposta

1

Se encapsularmos a string inicial em ' s em vez de " s, a $q não será imediatamente expandida. Podemos então expandi-lo mais tarde usando eval :

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

Infelizmente, o \n não é expandido, os ' s e " s são perdidos e o \" s passa a " s.

Saída:

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

Estamos bem perto, mas tentar consertar o escape com sed acaba se tornando um tanto complicado.

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

  • Parte 1: defina alguns dados (por exemplo, uma variável) que contenha 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. (Lidar com o envolvimento e o escape necessário para a parte 1 aqui.)

Aqui está uma tentativa grosseira inicial de que:

#!/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 o \n ser sempre interpretado e o \ s sendo perdido. Precisamos de alguma maneira de escapar da string de dados quando a imprimirmos novamente.

Aqui está uma melhoria que usa várias chamadas para echo para evitar os problemas com \n s.

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

Ela sofre de uma pequena falha que é difícil de superar, perdendo ' 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 com problemas de escape. Boa sorte!

    
por 13.02.2016 / 18:40