简体   繁体   中英

How to use printf “%q ” in bash?

I would like to print out augments of a function to a file. I was told a command printf "%q ", whose instruction is following,

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

On the basis of instruction above, I tried following code.

#!/bin/bash
# file name : print_out_function_augs.sh

output_file='output.txt'

function print_augs() {
  printf "%q " "$@" >> "${output_file}"
  echo >> "${output_file}"
}

print_augs a 'b c'

cat "${output_file}"
rm "${output_file}"

and run

bash print_out_function_augs.sh

The results are following,

a b\ c

I expected the results as

a 'b c'

which is the original augments to print_augs function.

Why does the output and the original augments are different? Or can I print out the original augments as they are?

Thank you very much.

Bear this in mind when using %q :

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

Emphasis mine. printf is free to reformat the arguments any way it likes as long as the input can be reused in the shell . However this is not the reason your input looks the way it does.

In Bash the ' character is a string delimiter, which is how you tell bash "the following string contains special characters like spaces, and these special characters should not be parsed by Bash". The quotes do not get passed to the commands that get called. What the command sees is something like this:

Command:
  printf "%q" a 'b c'

Received args:
  printf::arg0:  printf
  printf::arg1:  %q
  printf::arg2:  a
  printf::arg3:  b c

Note that arg3 does not have the quotes surrounding it. Bash does not pass them on.

When printf prints the args out, it does not know that there were quotes around bc , so it does not print them. But it does know that the space between 'b' and 'c' is a special shell character, and puts the \\ in front to escape it.

This is true for all bash functions/commands, so bear in mind that the same happens when you call print_augs too.

If you want to maintain quotes around your strings, you'll need to double quote them so that Bash doesn't parse them:

function print_augs2() {
  echo "$@" >> "${output_file}"
}

print_augs2 a "'b c'"

# Output: a 'b c'

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