简体   繁体   中英

Using printf %q to pass arguments with spaces

Suppose I have a script that prints out the number of arguments passed to it:

# file: num_args

echo "Number of arguments: $#"

Now my question pertains to the following invocations:


> ./num_args a b c
> Number of arguments: 3 # As I would expect.

> ./num_args "a b c"
> Number of arguments: 1 # As I would expect.

> ./num_args a\ b\ c
> Number of arguments: 1 # As I would expect.

> printf "%q\n" "a b c"
> a\ b\ c                # As I would expect.

> ./num_args $(printf "%q" "a b c")
> Number of arguments: 3 # NOT as I would expect.

Given that the printf man page states that

 %q     ARGUMENT is printed in a format that can be reused as shell input, escaping non-printable characters with the proposed POSIX $'' syntax.

I am not sure what happens in the last case above.

printf %q output is escaped correctly to be parsed as source code by a shell interpreter .

However, unquoted expansions aren't parsed as source code; they go only through string-splitting and glob-expansion phases. (This is a Good Thing: Otherwise handling untrusted filenames or other potentially-dangerous content in shell scripts would be nearly impossible).

You can substitute this output into a shell command, as in sh -c "...$foo..." or eval "...$foo..." or ssh somehost "...$foo..." ; it can't (shouldn't) just be used unquoted.


Some important references:

  • BashFAQ #50 explains why strings containing source code can't be used by expanding them unquoted.
  • BashFAQ #48 explains the risks involved in using eval (one of the families of workarounds discussed above).

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