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 enabledelayedexpansion
em arquivos em lote).Observe que quero uma solução para sh
, não bash
ou 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 $q
nã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 \n
nã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 sed
acaba 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 \n
ser 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 echo
para evitar 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"
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!