可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I'm confused in the way bash parses input and performs expansion.
For input say, \'"\"hello world\"" passed as argument in bash to a script that displays what its input is, I'm not exactly sure how Bash parses it.
Example,
var=\'"\"hello world\"" ./displaywhatiget.sh "$var" I got '"hello world"
I understand that the double quotes in "$var" tells bash to treat the value of var together. However, what I don't understand is when is the backslash escaping and double-quoted parsing for the value takes place in bash's expansion process.
I'm coming from shell-operation, and shell expansion.
回答1:
All of the interesting things happen in the assignment, var=\'"\"hello world\"". Let's break it down:
\' - this is an escaped single-quote. Without the escape, it would start a single-quoted string, but escaped it's just a literal single-quote. Thus, the final string will start with '. " - this starts a double-quoted string. \" - an escaped double-quote; like the escaped single-quote, this gets treated as a literal double-quote, so " will be the second character of the final string. hello world - since we're still in a double-quoted string, this just gets included literally in the final string. Note that if we weren't in double-quotes at this point, the space would've marked the end of the string. \" - another escaped double-quote; again, included literally so the last character of the final string will be ". " - this closes the double-quoted string.
Thus, var gets assigned the value '"hello world". In ./displaywhatiget.sh "$var", the double-quotes mean that $var gets replaced by var's value, but no further interpretation is done; that's just passed directly to the script.
UPDATE: When using set -vx, bash prints the assignment in a somewhat strange way. As I said in a comment, what it does is take the original command, parse it (as I described above) to figure out what it means, then back-translate that to get an equivalent command (i.e. one that'd have the same effect). The equivalent command it comes up with is var=''\''"hello world"'. Here's how that would be parsed:
'' - this is a zero-length single-quoted string; it has no effect whatsoever. I'm not sure why bash includes it. I'm tempted to call it a bug, but it's not actually wrong, just completely pointless. BTW, if you want an example of quote removal, here it is: in this command, these quotes would just be removed with no trace left. \' - this is an escaped single-quote, just like in the original command. The final string will start with '. ' - this starts a single-quoted string. No interpretation at all is performed inside single-quotes, except for looking for the close-quote. "hello world" - since we're in a single-quoted string, this just gets included literally in the final string, including the double-quotes and space. ' - this closes the single-quoted string.
so it gets the same value assigned to var, just written differently. Any of these would also have the same effect:
var=\''"hello world"' var="'\"hello world\"" var=\'\"hello\ world\" var="'"'"hello world"' var=$'\'"hello world"'
...and many others. bash could technically have printed any of these under set -vx.
回答2:
The parsing of the \-prefixed escape sequences happens on assignment:
var=\'"\"hello world\""
causes Bash to store the following literal in $var: '"hello world".
On later referencing $var inside a double-quoted string ("$var") the above literal becomes a literal part of that double-quoted string - no interpretation of the value of $var is performed at this point.
What double-quoted strings expand to is treated as a single word (argument) by the shell (after removing the enclosing double quotes, a process called quote removal).