![遅れた拡大](https://rvso.com/image/83446/%E9%81%85%E3%82%8C%E3%81%9F%E6%8B%A1%E5%A4%A7.png)
私は quine .sh スクリプトを作りたいのですが、これまでに作ったのは次のものです:
quine.sh
:
#!/bin/sh
q="#!/bin/sh\nq=$q;echo \$q";echo $q
この行に注目してください:
q="#!/bin/sh\nq=$q;echo \$q";echo $q
$q
(in )の最初の出現時に\nq=$q
、まず変数の残りの部分を設定し、次にこの部分 (setlocal enabledelayedexpansion
バッチ ファイル内の何かの行) を設定します。移植性が欲しいので、 や他の何かでsh
はなくの解決策が欲しいことに注意してください。bash
また、コードを短くする方法などのヒントも提供しないでください。上記の問題に対する解決策だけが欲しいのです。
答え1
'
最初の文字列をs ではなく sで囲むと"
、 は$q
すぐには展開されません。 次のようにして後で展開できますeval
。
#!/bin/sh
q='#!/bin/sh\nq=$q;eval "echo \"\$q\""';eval "echo \"$q\""
残念ながら、は\n
展開されず、'
s と"
s は失われ、\"
s は s になります"
。
出力:
#!/bin/sh\nq=#!/bin/sh\nq=$q;eval "echo \"\$q\"";eval echo "$q"
かなり近いのですが、脱出を修正しようとすると、sed
かなり面倒になります。
jw013 のリンクでは、かなり理解しやすいアプローチが推奨されています。
- パート1: プログラムの2番目の部分を含むデータ(変数など)を定義します。
- パート 2: データを使用してプログラムの最初の部分を出力し、次にそのデータを使用してプログラムの 2 番目の部分を出力します。(パート 1 に必要な折り返しとエスケープはここで処理します。)
以下は、そのための最初の大まかな試みです。
#!/bin/sh
data="echo -e \"#!/bin/sh\ndata=\"\$data\"\"\\n\$data"
echo -e "#!/bin/sh\ndata=\"$data\"\n$data"
出力:
#!/bin/sh
data="echo -e "#!/bin/sh
data="$data""
$data"
echo -e "#!/bin/sh
data="$data""
$data
この試みは、 が\n
常に解釈され、 が\
失われるという問題を抱えています。 再度印刷するときに、データ文字列をエスケープする方法が必要です。
echo
ここでは、 の問題を回避するために複数の呼び出しを使用する改善を示します\n
。
#!/bin/sh
data='echo "#!/bin/sh"\necho "data=$data"\necho -e "$data"'
echo "#!/bin/sh"
echo "data='$data'"
echo -e "$data"
克服するのが難しい小さな欠陥が 1 つあり、'
出力に が欠落しています (中央のecho
)。
#!/bin/sh
data='echo "#!/bin/sh"\necho "data=$data"\necho -e "$data"'
echo "#!/bin/sh"
echo "data=$data"
echo -e "$data"
私がお伝えしたいのは以上です。問題を回避するための出発点をいくつかご紹介します。頑張ってください!