In a way, it's not a quoting problem, it's an expansion problem. Variable expansion is not text replacement, and the data you get from the variable is not parsed as code, meaning neither quotes nor backslash escapes or any other shell syntax is processed. Instead, the expanded value is word-split on whitespace, any whitespace. This means you can't use word splitting to store multiple arbitrary strings in one string.
The tr
command you used seems to work, because adding single quotes to its argument doesn't change what it does with the o
s. As Chris Davies mentioned in a comment, if you do this:
$ t="tr -d 'oo'"
$ echo "don't forget" | $t
dnt frget
you'll see the quotes got included in the list of characters for tr
to remove. tr
got the argument 'oo'
, not the argument oo
.
If you wanted to have tr
remove spaces, you'd run into issues, same as with cut
:
$ t="tr -d ' '"
$ echo "don't forget" | $t
usage: tr [-Ccsu] string1 string2
tr [-Ccu] -d string1
tr [-Ccu] -s string1
tr [-Ccu] -ds string1 string2
That tries to run tr
with the three arguments -d
, '
and '
, which doesn't match how it's supposed to be used, so it prints the usage help.
The way to do it is to create a function instead, e.g.:
c() {
cut -d \ -f 2
}
echo "foo bii doo" | c
giving bii
.
See:
echo "don't forget" | $t
– Chris Davies Nov 26 '23 at 11:55$c
will be subject to word splitting (and globbing) - so' '
becomes two separate tokens'
and'
. See also How can we run a command stored in a variable? – steeldriver Nov 26 '23 at 12:02