Если мы обернем начальную строку в '
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 рекомендует довольно понятный подход:
Вот первоначальная грубая попытка:
#!/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
s.
#!/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"
Это все, что у меня есть для вас. Некоторые отправные точки для решения проблем с экранированием. Удачи!