Задержка расширения

Задержка расширения

Я хочу создать скрипт 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\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: Используйте данные для вывода первой части программы, а затем используйте данные для вывода второй части программы. (Здесь обработайте перенос и экранирование, необходимые для части 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что всегда интерпретируется, а \s теряется. Нам нужен какой-то способ экранировать строку данных, когда мы печатаем ее снова.


Вот улучшение, которое использует множественные вызовы echoдля того, чтобы избежать проблем с \ns.

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

Он страдает от одного маленького недостатка, который трудно устранить: 'в выходных данных отсутствует s (в середине echo):

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

Это все, что у меня есть для вас. Некоторые отправные точки для выхода из проблем. Удачи!

Связанный контент