2015-05-03 60 views
1

我想了解如何在sh中編寫嵌套轉義序列。我已經需要通過一個例子來說明,我想寫這樣的事情bash/sh嵌套轉義序列

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,不是現代系統上的Bourne。伯恩是一個更老的殼(70年代,90年代初)。 –

+0

順便說一句,如果使用bash而不是POSIX sh,通用的途徑是將''printf%q''傳遞給另一個shell的任意內容。 (因此:因爲你的問題是明確詢問'/ 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提供了一種明確的方法來要求shell將數據轉義爲eval-safe,與printf %q

因此,使用bash:

$ 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 SH,第三方庫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,VS推) ...

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