2

I noticed that this works fine (will print only the PID of unattended-upgrades process):

lslocks | awk '/unattended-upgrades/ { print $2 }'

But this effectively ignores the print part (will print the entire line):

bash -c "lslocks | awk '/unattended-upgrades/ { print $2 }'"

This is an Ubuntu 18.04 and Bash version 4.4.20.

What is spacial about bash -c that causes this?

Stéphane Chazelas
  • 522,931
  • 91
  • 1,010
  • 1,501
foki
  • 219
  • 2
  • 12

1 Answers1

6

There's nothing special about bash -c here - it's the fact that the outer double quotes permit expansion of $2 by the interactive shell:

$ set -x
$ bash -c "echo foo bar | awk '{ print $2 }'"
+ bash -c 'echo foo bar | awk '\''{ print  }'\'''
foo bar

(The "gotcha" here is that single quotes are not special inside double quotes; the outer double quotes "preserve their literal value". See Bash Reference Manual 3.1.2.3 Double Quotes.)

Compare:

$ bash -c "echo foo bar | awk '{ print \$2 }'"
+ bash -c 'echo foo bar | awk '\''{ print $2 }'\'''
bar
steeldriver
  • 78,509
  • 12
  • 109
  • 152
  • Ouch. That hurts. – foki Mar 18 '22 at 01:59
  • 3
    @foki quoting and escaping in shell are always a pain. It's something you just have to get used to and learn how to deal with...and it gets worse if you need multiple nested levels of quoting (e.g. with `bash -c`, `ssh`, and many others) as in your Q. See [Why does my shell script choke on whitespace or other special characters?](https://unix.stackexchange.com/questions/131766/why-does-my-shell-script-choke-on-whitespace-or-other-special-characters) and be sure to follow the link to the [quoting](https://unix.stackexchange.com/questions/tagged/quoting) tag. – cas Mar 18 '22 at 03:46
  • @cas Thank you for the references, they are very useful. – foki Mar 18 '22 at 05:32