This is a shell command:
set hello "hello" "hello world"
Because it is a shell command, the shell performs quote removal as the last step before executing the command.
Contrast that with the text in a file:
$ cat file
hello "hello" "hello world"
When the shell reads this file, it treats the quotes as just another character. The quotes in this file never appear directly on a command line and they are, consequently, not subject to quote removal.
Documentation
From the section in man bash
discussing expansions:
Quote Removal
After the preceding expansions, all unquoted occurrences of the characters \, ', and " that did not result from one of the above
expansions are removed.
How word splitting and quote removal interact
Bash does word splitting before it does quote removal. That is important, for example, for this command:
set hello "hello" "hello world"
When the shell does its word splitting, it finds three arguments to the set
command. It is only as the last step before executing set
that the shell does quote removal. Since no further word splitting is done, the number of arguments to set
remains as three.
Let's contrast the above with the result of reading a line from the file:
$ cat file
hello "hello" "hello world"
$ read line <file
$ echo "$line"
hello "hello" "hello world"
As discussed above, the shell does no quote removal on the contents of line
. Now, let's use $line
as the argument to set
:
$ set $line
$ echo $#
4
Four arguments are found. Those arguments are:
$ echo 1=$1 2=$2 3=$3 4=$4
1=hello 2="hello" 3="hello 4=world"
As you can see, the quotes in the file are treated as just plain ordinary characters, the same as, say, h
or e
. Consequently, "hello world"
from the file is expanded as two words, each having one quote character.