4

Can someone explain why I cannot store the cut command in a variable??

user:~$ echo "foo bii doo" | cut -d ' ' -f 2
bii # as expected
# now put cut command into a variable:
user:~$ c="cut -d ' ' -f 2"
user:~$ echo "foo bii doo" | $c
cut: "'": No such file or directory
user:~$ c="cut -d \  -f 2"
user:~$ echo "foo bii doo" | $c
foo bii doo

It is not a general quoting problem because tr works:

user:~$ t="tr -d 'oo'"
user:~$ echo "foo bii doo" | $t
f bii d

(I am on Debian 12 using bash)
Solved the problem in other ways already. I ask just to know why I wasted 3 hours debugging :)

1 Answers1

8

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 os. 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:

ilkkachu
  • 138,973
  • Thank you for this elaborate answer. Lesson learned, as @chris-davies also commented: Don't try to put a command in a simple scalar (string) variable – archygriswald Nov 26 '23 at 14:38