17

The following script yielded an unexpected output:

printf "escaped slash: \\ \n"
printf "2 escaped slashes: \\\\ \n"
printf "3 escaped slashes: \\\\\\ \n"
printf "4 escaped slashes: \\\\\\\\ \n"

Run as a bash script under Ubuntu 14, I see:

escaped slash: \
2 escaped slashes: \ 
3 escaped slashes: \\ 
4 escaped slashes: \\

Err.. what?

Charney Kaye
  • 3,667
  • 6
  • 41
  • 54

3 Answers3

12

Assuming that printf FORMAT string is surrounded by double quotes, printf takes one additional level of expansion, compared to e.g. echo (both being shell builtin commands).

What you expect from printf can actually be achieved using single quotes:

printf '1 escaped slash:   \\ \n'
printf '2 escaped slashes: \\\\ \n'
printf '3 escaped slashes: \\\\\\ \n'
printf '4 escaped slashes: \\\\\\\\ \n'

outputs:

1 escaped slash:   \
2 escaped slashes: \\
3 escaped slashes: \\\
4 escaped slashes: \\\\
Eugeniu Rosca
  • 5,177
  • 16
  • 45
  • Note this works because you prevent `bash` from removing any backslashes before `printf` sees the argument. – chepner Jul 05 '15 at 02:45
  • @chepner: I agree. It seems the order of evaluation is: 1) `bash` expands the `FORMAT` string *(only if surrounded by double quotes!)*. 2) `printf` combines the `ARGUMENTS` and the `FORMAT` into one string. 3) The final string is expanded again (i.e. \\ becomes \ ). 4) The result is finally printed. – Eugeniu Rosca Jul 05 '15 at 12:03
  • Close; `printf` only process the `FORMAT` before inserting the arguments; compare `printf '\n'` with `printf '%s' '\n'`. – chepner Jul 05 '15 at 13:01
5

printf is a bash builtin. Look at help printf:

printf [-v var] format [arguments]
      Formats and prints ARGUMENTS under control of the FORMAT.

You should pass the format and the argument. So add the format "%s\n" before the argument:

printf "%s\n" "escaped slash: \\"
printf "%s\n" "2 escaped slashes: \\\\"
printf "%s\n" "3 escaped slashes: \\\\\\"
printf "%s\n" "4 escaped slashes: \\\\\\\\"

Output:

escaped slash: \ 
2 escaped slashes: \\ 
3 escaped slashes: \\\ 
4 escaped slashes: \\\\ 
Cyrus
  • 84,225
  • 14
  • 89
  • 153
1

An additional note on what Cyrus said:

If you quote the printf's ARGUMENT with single quotes, you should save a lot of backslashes. For example,

printf "%s\n" 'escaped slash: \'
printf "%s\n" '2 escaped slashes: \\'
printf "%s\n" '3 escaped slashes: \\\'
printf "%s\n" '4 escaped slashes: \\\\'

outputs

1 escaped slash:   \
2 escaped slashes: \\
3 escaped slashes: \\\
4 escaped slashes: \\\\
Kevin
  • 143
  • 1
  • 7