2015-05-03 3 views
1

Я хочу понять, как писать вложенные escape-последовательности в sh. Я к необходимости проиллюстрировать на примере, я хочу написать что-то вроде этогоbash/sh вложенные escape-последовательности

sh -c sh -c sh -c sh -c sh -c date 

Ожидаемый вывод: текущая дата

Я попытался следующие, может идти до 2 уровней вложенности, но потерял:

sh -c date 
Sat May 2 18:38:38 PDT 2015 
sh -c "sh -c date" 
Sat May 2 18:38:43 PDT 2015 
sh -c "sh -c \"sh -c date\"" 
Unmatched ". 

Я хочу использовать общий путь, как показано на 5 уровнях вложенности.

+0

'/ bin/sh' - это POSIX sh, а не Bou на современных системах. Борн - гораздо более древняя оболочка (70-е, против начала 90-х годов). –

+0

Кстати, если вы работаете с bash, а не с POSIX sh, универсальный способ избежать произвольного содержимого, который должен быть передан другой оболочке, - это 'printf% q'. (Таким образом: поскольку ваш вопрос явно спрашивает о '/ bin/sh', его не следует помечать' bash', ответ для bash будет другим). –

+0

«bash/sh» так же плохо, как «C/C++». Это два отдельных языка. Они должны получить два отдельных вопроса, если вам действительно нужно знать оба. –

ответ

2

при условии, что это то, что вы имели в виду ...

sh -c "sh -c \"sh -c \\\" sh -c \\\\\\\" sh -c \\\\\\\\\\\\\\\" date \\\\\\\\\\\\\\\" \\\\\\\" \\\" \" " 

Это становится довольно некрасиво, и если честно, я не знаю, почему вы никогда не хотите, чтобы это сделать, но эй, там есть. Гнездо прочь!

3

В отличие от POSIX sh, bash предоставляет явный способ попросить оболочку избежать данных, чтобы они были безопасными по значению, с printf %q.

Таким образом, с Баш:

$ command_str=date 
$ nest() { printf 'sh -c %q\n' "$1"; } 
$ nest "$command_str" 
sh -c date 
$ nest "$(nest "$command_str")" 
sh -c sh\ -c\ date 
$ nest "$(nest "$(nest "$command_str")")" 
sh -c sh\ -c\ sh\\\ -c\\\ date 

... и так далее, до бесконечности.


В POSIX ш, третья сторона библиотека Push может быть использована для того же цели:

$ source push.sh 
$ command_str=date 
$ Push -c command_str sh -c "$command_str"; echo "$command_str" 
sh -c date 
$ Push -c command_str sh -c "$command_str"; echo "$command_str" 
sh -c 'sh -c date' 
$ Push -c command_str sh -c "$command_str"; echo "$command_str" 
sh -c 'sh -c '\''sh -c date'\' 
$ Push -c command_str sh -c "$command_str"; echo "$command_str" 
sh -c 'sh -c '\''sh -c '\''\'\'\''sh -c date'\''\'\' 

... и т.д..


Если вы хотите автоматизировать вложенности для произвольного числа уровней:

nest() { 
    local cmd_str level >/dev/null 2>&1 ||: "in POSIX sh, local may not exist" 
    level=$1; shift 

    ## in bash 
    printf -v cmd_str '%q ' sh -c "[email protected]"; cmd_str=${cmd_str%" "} 

    ## in POSIX sh, using https://github.com/vaeth/push 
    #Push -c cmd_str sh -c "[email protected]" 

    if [ "$level" -gt 1 ]; then 
    nest "$((level - 1))" "$cmd_str" 
    else 
    printf '%s\n' "$cmd_str" 
    fi 
} 

Тогда:

nest 5 date 

... даст вам (с printf %q, против толчка) ...

sh -c sh\ -c\ sh\\\ -c\\\ date 
Смежные вопросы