0

I am trying to redirect the output of a command that contains couple of user input variables to an array. I first tried this script -

echo "Type the ACL name"
read acl
echo "Type the DATACENTER name"
read dc
echo "ACL is $acl, DC is $dc"
mkdir ~/$acl
device=($(grep -iEr $acl ~/sync-configs/$dc/configs/* | awk -F ':' {'print $1'} | awk -F '/' {'print $NF'} | sort | uniq))

The script created the ~/acl directory just fine but the grep did not work for me. Then, after doing some research, I adjusted the grep to put the variables in double quotes, like this -

echo "Type the ACL name"
read acl
echo "Type the DATACENTER name"
read dc
echo "ACL is $acl, DC is $dc"
mkdir ~/$acl
device=($(grep -iEr "$acl" ~/sync-configs/"$dc"/configs/* | awk -F ':' {'print $1'} | awk -F '/' {'print $NF'} | sort | uniq))

This seems to work fine and I am able to see elements in the device array.

My question is why do I need to put the $acl and $dc quotes when feeding them to the array but the command mkdir ~/$acl doesn't require any quotes? Can some one provide clarity on this?

  • That would depend on what you enter for acl and dc, wouldn't it. – Satō Katsura May 13 '17 at 05:35
  • Ah...my acl input is a string. So..that is why i need to escape it with quotes in the grep command? But then, why dont I need to escape it in the mkdir ~/acl command? – user168115 May 13 '17 at 05:40
  • That isn't remotely what I said. shrug – Satō Katsura May 13 '17 at 05:41
  • What matters is the value you entered at the read prompt, not the type. In a shell there is only one type that is a first class citizen - strings. – the_velour_fog May 13 '17 at 05:51
  • Related: http://unix.stackexchange.com/questions/171346/security-implications-of-forgetting-to-quote-a-variable-in-bash-posix-shells – Kusalananda May 13 '17 at 06:47
  • @the_velour_fog, well actually, Bash variables can be declared integers too. – ilkkachu May 13 '17 at 10:23
  • @ilkkachu thats interesting. a quick scan of man page reveals If the variable has its integer attribute set, then value is evaluated as an arithmetic expression even if the $((...)) expansion is not used (see Arithmetic Expansion below). – the_velour_fog May 13 '17 at 10:28
  • @the_velour_fog, in an assignment, yeah. And in read... Which makes for some amusing effects if the value from read happens to be the name of a variable. I was going to say something about integer variables being safe from word splitting, but then someone is going to set IFS=2, so nevermind. – ilkkachu May 13 '17 at 10:51
  • @user168115, if the acl var contains only a single word, the mkdir works as you expect. Try the same with acl set to two words, say foo bar. – ilkkachu May 13 '17 at 10:54
  • @ilkkachu yes I have generally avoided typeset and declare except which absolutely necessary, e.g. typeset -A some_array especially because different shells seem to use them differently – the_velour_fog May 13 '17 at 10:59

1 Answers1

1

Generally speaking quotes are used to preserve the literal meaning of values and to avoid the interpreter doing transformations on special characters and other operations, such as parameter expansion and word splitting.
If you are using " to quote words, variables will be expanded still, but no word splitting will be performed.
Word splitting is the process of the shell taking a string and - conceptually breaking it up into different words, or tokens.
So if you entered this at the read prompt

bangalore data center

you command would be expanded like so:
With quotes

grep -iEr "$acl" ~/sync-configs/"$dc"/configs/*

becomes

grep -iEr bangalore data center ~/sync-configs/"$dc"/configs/*
          ^^^^^^^^^^^^^^^^^^^^   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
            pattern argument      File/s argument to grep
            to grep

Without quotes

grep -iEr $acl ~/sync-configs/"$dc"/configs/*

becomes

grep -iEr bangalore data center ~/sync-configs/"$dc"/configs/*
          ^^^^^^^^^ |^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
            pattern |    File/s argument to grep

note: in the above $dc would have also been expanded.