简体   繁体   中英

bash/sh nested escape sequences

I want to understand how to write nested escape sequences in sh . I have to need illustrated by an example, I want to write something like this

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

Expected Output: current date

I tried the following, could go upto 2 levels of nesting but lost:

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 ".

I want a general purpose way to escape like the 5 levels of nesting shown above.

Unlike POSIX sh, bash provides an explicit way to ask the shell to escape data to be eval-safe, with printf %q .

Thus, with 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

...and so on, ad infinitum.


In POSIX sh, the third-party library Push can be used for that same purpose:

$ 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'\''\'\'

...etc.


If you wanted to automate the nesting for an arbitrary number of levels:

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 "$@"; cmd_str=${cmd_str%" "}

  ## in POSIX sh, using https://github.com/vaeth/push
  #Push -c cmd_str sh -c "$@"

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

Then:

nest 5 date

...would give you (with printf %q , vs push)...

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

assuming this is what you meant...

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

This gets pretty ugly, and honestly I'm not sure why you'd ever want to do this, but hey, there it is. Nest away!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM