Ich möchte ein Quine-SH-Skript erstellen und das habe ich bisher gemacht
quine.sh
::
#!/bin/sh
q="#!/bin/sh\nq=$q;echo \$q";echo $q
Konzentrieren Sie sich auf diese Zeile:
q="#!/bin/sh\nq=$q;echo \$q";echo $q
Beim ersten Vorkommen von $q
(in \nq=$q
) möchte ich zuerst den Rest der Variable setzen und dann diesen Teil (irgendeine Zeile setlocal enabledelayedexpansion
in Batchdateien).Beachten Sie, dass ich eine Lösung für möchte sh
, nicht für bash
oder etwas anderes, da ich Portabilität möchte. Geben Sie mir auch keine Tipps, wie ich meinen Code kürzer machen kann usw. Ich möchte nur eine Lösung für das oben genannte Problem.
Antwort1
Wenn wir den Anfangsstring in '
s statt in s einschließen , wird "
er nicht sofort erweitert. Wir können ihn dann später erweitern mit :$q
eval
#!/bin/sh
q='#!/bin/sh\nq=$q;eval "echo \"\$q\""';eval "echo \"$q\""
Leider \n
wird das nicht erweitert, die '
s und "
s gehen verloren und aus dem \"
s wird ein "
s.
Ausgabe:
#!/bin/sh\nq=#!/bin/sh\nq=$q;eval "echo \"\$q\"";eval echo "$q"
Wir sind ziemlich nah dran, aber der Versuch, das Entkommen zu beheben, sed
erweist sich letztendlich als ziemlich mühselig.
Der Link von jw013 empfiehlt einen ziemlich verständlichen Ansatz:
- Teil 1: Definieren Sie einige Daten (z. B. eine Variable), die den zweiten Teil des Programms enthalten
- Teil 2: Verwenden Sie die Daten, um den ersten Teil des Programms auszugeben, und verwenden Sie die Daten dann, um den zweiten Teil des Programms auszugeben. (Behandeln Sie hier das für Teil 1 erforderliche Umbrechen und Escapen.)
Hier ist ein erster, grober Versuch hierzu:
#!/bin/sh
data="echo -e \"#!/bin/sh\ndata=\"\$data\"\"\\n\$data"
echo -e "#!/bin/sh\ndata=\"$data\"\n$data"
Ausgabe:
#!/bin/sh
data="echo -e "#!/bin/sh
data="$data""
$data"
echo -e "#!/bin/sh
data="$data""
$data
Dieser Versuch leidet darunter, dass \n
immer interpretiert wird und die \
s verloren gehen. Wir brauchen eine Möglichkeit, den Datenstring zu escapen, wenn wir ihn erneut drucken.
Hier ist eine Verbesserung, die mehrere Aufrufe verwendet, echo
um die Probleme mit \n
s zu vermeiden.
#!/bin/sh
data='echo "#!/bin/sh"\necho "data=$data"\necho -e "$data"'
echo "#!/bin/sh"
echo "data='$data'"
echo -e "$data"
Es weist einen winzigen, schwer zu behebenden Fehler auf: '
In der Ausgabe (in der Mitte echo
) fehlen s:
#!/bin/sh
data='echo "#!/bin/sh"\necho "data=$data"\necho -e "$data"'
echo "#!/bin/sh"
echo "data=$data"
echo -e "$data"
Das ist alles, was ich für Sie habe. Einige Ansatzpunkte zum Entkommen von Problemen. Viel Glück!