Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use printf "%q " in bash?

Tags:

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.

like image 321
mora Avatar asked Nov 13 '16 12:11

mora


People also ask

What is %q in printf?

Characters in the format string are copied to the output or, if a % is encountered, are used to format an item. In addition to the standard formats, %b causes printf to expand backslash escape sequences (for example \n for newline), and %q outputs an item that can be used as shell input.

Can we use printf in shell script?

“printf” command in Linux is used to display the given string, number or any other format specifier on the terminal window. It works the same way as “printf” works in programming languages like C. Note: printf can have format specifiers, escape sequences or ordinary characters.

Can we use printf in bash?

The bash printf command is a tool used for creating formatted output. It is a shell built-in, similar to the printf() function in C/C++, Java, PHP, and other programming languages. The command allows you to print formatted text and variables in standard output.

How do I print in bash?

To print a string in Bash, use echo command. Provide the string as command line argument to echo command.


1 Answers

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 b c, 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'
like image 104
Karl Nicoll Avatar answered Oct 06 '22 00:10

Karl Nicoll