Why does bash not remove backslash in the quote removal step in this example?
up vote
1
down vote
favorite
In bash
$ va='\abc'
$ echo $va
\abc
In the assignment va='\abc'
, the single quotes preserve the two backslashes in the value of va
.
In the echo command echo $va
, Is it correct that bash first performs parameter expansion on $va
(expand it to \abc
), and then performs quote removal on the result of parameter expansion? Quote removal removes backslash and quotes, but why are the two backslashes still preserved? I expect the result to be abc
. For comparison
$ echo \abc
abc
Do I miss something in the bash manual? I appreciate that someone can point out what I miss.
Thanks.
bash
add a comment |
up vote
1
down vote
favorite
In bash
$ va='\abc'
$ echo $va
\abc
In the assignment va='\abc'
, the single quotes preserve the two backslashes in the value of va
.
In the echo command echo $va
, Is it correct that bash first performs parameter expansion on $va
(expand it to \abc
), and then performs quote removal on the result of parameter expansion? Quote removal removes backslash and quotes, but why are the two backslashes still preserved? I expect the result to be abc
. For comparison
$ echo \abc
abc
Do I miss something in the bash manual? I appreciate that someone can point out what I miss.
Thanks.
bash
1
I think you are forgetting that using ' takes out the meaning of what follows ahead.
– Rui F Ribeiro
2 days ago
I am asking aboutecho $va
, where there is no single quote stored in$va
or involved in any way.
– Tim
2 days ago
1
@Tim Quote and escape parsing, removal, etc all happen before variable references are expanded. The only port-processing done on (non-quoted) variable expansions is word splitting and wildcard expansion.
– Gordon Davisson
2 days ago
add a comment |
up vote
1
down vote
favorite
up vote
1
down vote
favorite
In bash
$ va='\abc'
$ echo $va
\abc
In the assignment va='\abc'
, the single quotes preserve the two backslashes in the value of va
.
In the echo command echo $va
, Is it correct that bash first performs parameter expansion on $va
(expand it to \abc
), and then performs quote removal on the result of parameter expansion? Quote removal removes backslash and quotes, but why are the two backslashes still preserved? I expect the result to be abc
. For comparison
$ echo \abc
abc
Do I miss something in the bash manual? I appreciate that someone can point out what I miss.
Thanks.
bash
In bash
$ va='\abc'
$ echo $va
\abc
In the assignment va='\abc'
, the single quotes preserve the two backslashes in the value of va
.
In the echo command echo $va
, Is it correct that bash first performs parameter expansion on $va
(expand it to \abc
), and then performs quote removal on the result of parameter expansion? Quote removal removes backslash and quotes, but why are the two backslashes still preserved? I expect the result to be abc
. For comparison
$ echo \abc
abc
Do I miss something in the bash manual? I appreciate that someone can point out what I miss.
Thanks.
bash
bash
edited 2 days ago
asked 2 days ago
Tim
24.9k70239434
24.9k70239434
1
I think you are forgetting that using ' takes out the meaning of what follows ahead.
– Rui F Ribeiro
2 days ago
I am asking aboutecho $va
, where there is no single quote stored in$va
or involved in any way.
– Tim
2 days ago
1
@Tim Quote and escape parsing, removal, etc all happen before variable references are expanded. The only port-processing done on (non-quoted) variable expansions is word splitting and wildcard expansion.
– Gordon Davisson
2 days ago
add a comment |
1
I think you are forgetting that using ' takes out the meaning of what follows ahead.
– Rui F Ribeiro
2 days ago
I am asking aboutecho $va
, where there is no single quote stored in$va
or involved in any way.
– Tim
2 days ago
1
@Tim Quote and escape parsing, removal, etc all happen before variable references are expanded. The only port-processing done on (non-quoted) variable expansions is word splitting and wildcard expansion.
– Gordon Davisson
2 days ago
1
1
I think you are forgetting that using ' takes out the meaning of what follows ahead.
– Rui F Ribeiro
2 days ago
I think you are forgetting that using ' takes out the meaning of what follows ahead.
– Rui F Ribeiro
2 days ago
I am asking about
echo $va
, where there is no single quote stored in $va
or involved in any way.– Tim
2 days ago
I am asking about
echo $va
, where there is no single quote stored in $va
or involved in any way.– Tim
2 days ago
1
1
@Tim Quote and escape parsing, removal, etc all happen before variable references are expanded. The only port-processing done on (non-quoted) variable expansions is word splitting and wildcard expansion.
– Gordon Davisson
2 days ago
@Tim Quote and escape parsing, removal, etc all happen before variable references are expanded. The only port-processing done on (non-quoted) variable expansions is word splitting and wildcard expansion.
– Gordon Davisson
2 days ago
add a comment |
3 Answers
3
active
oldest
votes
up vote
5
down vote
accepted
Start with a simpler comparison:
$ echo '\abc'
\abc
$ echo \abc
abc
In the first command, the apostrophes do not become part of the argument to echo
because they have been used for quoting. All of the characters inside, including both backslashes, are passed to echo
.
In the second command, the first backslash quotes the second backslash. The one that was used for quoting does not become part of the argument to echo
. The other one is passed to echo
, along with the abc
(which was not quoted, but that doesn't matter because they are not metacharacters).
Now we're ready to talk about your command sequence
$ va='\abc'
$ echo $va
\abc
When the assignment command is executed, the apostrophes quote everything between them. The apostrophes do not become part of the value assigned, but everything else does, including both backslashes.
In the echo
command, there are no quoting characters. The value of va
is retrieved and inserted into the argument list. Now there is an argument containing 2 backslashes, but they don't function as quoting characters, because the parsing phases where we were looking for quoting characters was done before variable expansion.
Variable expansion is not like macro expansion. The resulting series of arguments is not fed back in to the full command line parser. Some post-processing is done (word-splitting and globbing) but there is not a second pass of quote removal and variable expansion.
When you want to build an argument list and reparse the whole thing as a new command line with all shell features available, you can use eval
. This is usually a bad idea because "all shell features" is a lot, and if you aren't careful, something bad can happen.
$ va='\abc'
$ eval echo $va
abc
Perfect, right?
$ va='\abc;rm -rf $important_database'
$ eval echo $va
abc
^C^C^C ARGH!
When you find yourself wanting to use shell quoting syntax inside the value of a shell variable, try to think of a different way to solve your problem.
add a comment |
up vote
3
down vote
Do I miss something in the bash manual?
Yes. From the manual:
After the preceding expansions, all unquoted occurrences of the
characters ‘’, ‘
'
’, and ‘"
’ that did not result from one of the
above expansions are removed.
The "preceding expansions" and "above expansions" here being parameter (variable) expansion, command substitution, etc.
Thanks. ........................
– Tim
2 days ago
add a comment |
up vote
0
down vote
The answer is simple, the line:
echo $va
does not contain quotes that need to be removed.
This is how the shell has been defined since more than 40 years already. Note that the Bourne Shell first appeared AT&T internally in 1976.
BTW: "quoting" in this regard meant characters with the 8th bit on in the 1970s. So this in a shell internal form of quoting.
Since the Bourne Shell has been reworked to support 8-bit characters, in the mid 1980s, this internal form of quotuing has been replaced by backslashes in the internal strings before any quoted character.
Today, the Bourne Shell works the following way:
Strings that are written in single quotes are replaced by the backslash form. This e.g. means that 'abc' is replaced by abc
Strings with explicitely typed backslashes are kept internally.
Strings with double quotes keep their double quotes, so "abc" remains internally "abc"
When doing parameter expansion, the shell replaces all kind of quoted strings (see three forms above) by the form with single backslashes before any char and this is what is removed while doing "quote removal".
BTW: the variable expansion:
abc=123
done with
command "$abc"
results in
command 123
before quote removal is done.
command $abc
results in
command 123
before quote removal is done.
add a comment |
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
5
down vote
accepted
Start with a simpler comparison:
$ echo '\abc'
\abc
$ echo \abc
abc
In the first command, the apostrophes do not become part of the argument to echo
because they have been used for quoting. All of the characters inside, including both backslashes, are passed to echo
.
In the second command, the first backslash quotes the second backslash. The one that was used for quoting does not become part of the argument to echo
. The other one is passed to echo
, along with the abc
(which was not quoted, but that doesn't matter because they are not metacharacters).
Now we're ready to talk about your command sequence
$ va='\abc'
$ echo $va
\abc
When the assignment command is executed, the apostrophes quote everything between them. The apostrophes do not become part of the value assigned, but everything else does, including both backslashes.
In the echo
command, there are no quoting characters. The value of va
is retrieved and inserted into the argument list. Now there is an argument containing 2 backslashes, but they don't function as quoting characters, because the parsing phases where we were looking for quoting characters was done before variable expansion.
Variable expansion is not like macro expansion. The resulting series of arguments is not fed back in to the full command line parser. Some post-processing is done (word-splitting and globbing) but there is not a second pass of quote removal and variable expansion.
When you want to build an argument list and reparse the whole thing as a new command line with all shell features available, you can use eval
. This is usually a bad idea because "all shell features" is a lot, and if you aren't careful, something bad can happen.
$ va='\abc'
$ eval echo $va
abc
Perfect, right?
$ va='\abc;rm -rf $important_database'
$ eval echo $va
abc
^C^C^C ARGH!
When you find yourself wanting to use shell quoting syntax inside the value of a shell variable, try to think of a different way to solve your problem.
add a comment |
up vote
5
down vote
accepted
Start with a simpler comparison:
$ echo '\abc'
\abc
$ echo \abc
abc
In the first command, the apostrophes do not become part of the argument to echo
because they have been used for quoting. All of the characters inside, including both backslashes, are passed to echo
.
In the second command, the first backslash quotes the second backslash. The one that was used for quoting does not become part of the argument to echo
. The other one is passed to echo
, along with the abc
(which was not quoted, but that doesn't matter because they are not metacharacters).
Now we're ready to talk about your command sequence
$ va='\abc'
$ echo $va
\abc
When the assignment command is executed, the apostrophes quote everything between them. The apostrophes do not become part of the value assigned, but everything else does, including both backslashes.
In the echo
command, there are no quoting characters. The value of va
is retrieved and inserted into the argument list. Now there is an argument containing 2 backslashes, but they don't function as quoting characters, because the parsing phases where we were looking for quoting characters was done before variable expansion.
Variable expansion is not like macro expansion. The resulting series of arguments is not fed back in to the full command line parser. Some post-processing is done (word-splitting and globbing) but there is not a second pass of quote removal and variable expansion.
When you want to build an argument list and reparse the whole thing as a new command line with all shell features available, you can use eval
. This is usually a bad idea because "all shell features" is a lot, and if you aren't careful, something bad can happen.
$ va='\abc'
$ eval echo $va
abc
Perfect, right?
$ va='\abc;rm -rf $important_database'
$ eval echo $va
abc
^C^C^C ARGH!
When you find yourself wanting to use shell quoting syntax inside the value of a shell variable, try to think of a different way to solve your problem.
add a comment |
up vote
5
down vote
accepted
up vote
5
down vote
accepted
Start with a simpler comparison:
$ echo '\abc'
\abc
$ echo \abc
abc
In the first command, the apostrophes do not become part of the argument to echo
because they have been used for quoting. All of the characters inside, including both backslashes, are passed to echo
.
In the second command, the first backslash quotes the second backslash. The one that was used for quoting does not become part of the argument to echo
. The other one is passed to echo
, along with the abc
(which was not quoted, but that doesn't matter because they are not metacharacters).
Now we're ready to talk about your command sequence
$ va='\abc'
$ echo $va
\abc
When the assignment command is executed, the apostrophes quote everything between them. The apostrophes do not become part of the value assigned, but everything else does, including both backslashes.
In the echo
command, there are no quoting characters. The value of va
is retrieved and inserted into the argument list. Now there is an argument containing 2 backslashes, but they don't function as quoting characters, because the parsing phases where we were looking for quoting characters was done before variable expansion.
Variable expansion is not like macro expansion. The resulting series of arguments is not fed back in to the full command line parser. Some post-processing is done (word-splitting and globbing) but there is not a second pass of quote removal and variable expansion.
When you want to build an argument list and reparse the whole thing as a new command line with all shell features available, you can use eval
. This is usually a bad idea because "all shell features" is a lot, and if you aren't careful, something bad can happen.
$ va='\abc'
$ eval echo $va
abc
Perfect, right?
$ va='\abc;rm -rf $important_database'
$ eval echo $va
abc
^C^C^C ARGH!
When you find yourself wanting to use shell quoting syntax inside the value of a shell variable, try to think of a different way to solve your problem.
Start with a simpler comparison:
$ echo '\abc'
\abc
$ echo \abc
abc
In the first command, the apostrophes do not become part of the argument to echo
because they have been used for quoting. All of the characters inside, including both backslashes, are passed to echo
.
In the second command, the first backslash quotes the second backslash. The one that was used for quoting does not become part of the argument to echo
. The other one is passed to echo
, along with the abc
(which was not quoted, but that doesn't matter because they are not metacharacters).
Now we're ready to talk about your command sequence
$ va='\abc'
$ echo $va
\abc
When the assignment command is executed, the apostrophes quote everything between them. The apostrophes do not become part of the value assigned, but everything else does, including both backslashes.
In the echo
command, there are no quoting characters. The value of va
is retrieved and inserted into the argument list. Now there is an argument containing 2 backslashes, but they don't function as quoting characters, because the parsing phases where we were looking for quoting characters was done before variable expansion.
Variable expansion is not like macro expansion. The resulting series of arguments is not fed back in to the full command line parser. Some post-processing is done (word-splitting and globbing) but there is not a second pass of quote removal and variable expansion.
When you want to build an argument list and reparse the whole thing as a new command line with all shell features available, you can use eval
. This is usually a bad idea because "all shell features" is a lot, and if you aren't careful, something bad can happen.
$ va='\abc'
$ eval echo $va
abc
Perfect, right?
$ va='\abc;rm -rf $important_database'
$ eval echo $va
abc
^C^C^C ARGH!
When you find yourself wanting to use shell quoting syntax inside the value of a shell variable, try to think of a different way to solve your problem.
answered 2 days ago
Wumpus Q. Wumbley
4,5901322
4,5901322
add a comment |
add a comment |
up vote
3
down vote
Do I miss something in the bash manual?
Yes. From the manual:
After the preceding expansions, all unquoted occurrences of the
characters ‘’, ‘
'
’, and ‘"
’ that did not result from one of the
above expansions are removed.
The "preceding expansions" and "above expansions" here being parameter (variable) expansion, command substitution, etc.
Thanks. ........................
– Tim
2 days ago
add a comment |
up vote
3
down vote
Do I miss something in the bash manual?
Yes. From the manual:
After the preceding expansions, all unquoted occurrences of the
characters ‘’, ‘
'
’, and ‘"
’ that did not result from one of the
above expansions are removed.
The "preceding expansions" and "above expansions" here being parameter (variable) expansion, command substitution, etc.
Thanks. ........................
– Tim
2 days ago
add a comment |
up vote
3
down vote
up vote
3
down vote
Do I miss something in the bash manual?
Yes. From the manual:
After the preceding expansions, all unquoted occurrences of the
characters ‘’, ‘
'
’, and ‘"
’ that did not result from one of the
above expansions are removed.
The "preceding expansions" and "above expansions" here being parameter (variable) expansion, command substitution, etc.
Do I miss something in the bash manual?
Yes. From the manual:
After the preceding expansions, all unquoted occurrences of the
characters ‘’, ‘
'
’, and ‘"
’ that did not result from one of the
above expansions are removed.
The "preceding expansions" and "above expansions" here being parameter (variable) expansion, command substitution, etc.
answered 2 days ago
muru
34.7k580153
34.7k580153
Thanks. ........................
– Tim
2 days ago
add a comment |
Thanks. ........................
– Tim
2 days ago
Thanks. ........................
– Tim
2 days ago
Thanks. ........................
– Tim
2 days ago
add a comment |
up vote
0
down vote
The answer is simple, the line:
echo $va
does not contain quotes that need to be removed.
This is how the shell has been defined since more than 40 years already. Note that the Bourne Shell first appeared AT&T internally in 1976.
BTW: "quoting" in this regard meant characters with the 8th bit on in the 1970s. So this in a shell internal form of quoting.
Since the Bourne Shell has been reworked to support 8-bit characters, in the mid 1980s, this internal form of quotuing has been replaced by backslashes in the internal strings before any quoted character.
Today, the Bourne Shell works the following way:
Strings that are written in single quotes are replaced by the backslash form. This e.g. means that 'abc' is replaced by abc
Strings with explicitely typed backslashes are kept internally.
Strings with double quotes keep their double quotes, so "abc" remains internally "abc"
When doing parameter expansion, the shell replaces all kind of quoted strings (see three forms above) by the form with single backslashes before any char and this is what is removed while doing "quote removal".
BTW: the variable expansion:
abc=123
done with
command "$abc"
results in
command 123
before quote removal is done.
command $abc
results in
command 123
before quote removal is done.
add a comment |
up vote
0
down vote
The answer is simple, the line:
echo $va
does not contain quotes that need to be removed.
This is how the shell has been defined since more than 40 years already. Note that the Bourne Shell first appeared AT&T internally in 1976.
BTW: "quoting" in this regard meant characters with the 8th bit on in the 1970s. So this in a shell internal form of quoting.
Since the Bourne Shell has been reworked to support 8-bit characters, in the mid 1980s, this internal form of quotuing has been replaced by backslashes in the internal strings before any quoted character.
Today, the Bourne Shell works the following way:
Strings that are written in single quotes are replaced by the backslash form. This e.g. means that 'abc' is replaced by abc
Strings with explicitely typed backslashes are kept internally.
Strings with double quotes keep their double quotes, so "abc" remains internally "abc"
When doing parameter expansion, the shell replaces all kind of quoted strings (see three forms above) by the form with single backslashes before any char and this is what is removed while doing "quote removal".
BTW: the variable expansion:
abc=123
done with
command "$abc"
results in
command 123
before quote removal is done.
command $abc
results in
command 123
before quote removal is done.
add a comment |
up vote
0
down vote
up vote
0
down vote
The answer is simple, the line:
echo $va
does not contain quotes that need to be removed.
This is how the shell has been defined since more than 40 years already. Note that the Bourne Shell first appeared AT&T internally in 1976.
BTW: "quoting" in this regard meant characters with the 8th bit on in the 1970s. So this in a shell internal form of quoting.
Since the Bourne Shell has been reworked to support 8-bit characters, in the mid 1980s, this internal form of quotuing has been replaced by backslashes in the internal strings before any quoted character.
Today, the Bourne Shell works the following way:
Strings that are written in single quotes are replaced by the backslash form. This e.g. means that 'abc' is replaced by abc
Strings with explicitely typed backslashes are kept internally.
Strings with double quotes keep their double quotes, so "abc" remains internally "abc"
When doing parameter expansion, the shell replaces all kind of quoted strings (see three forms above) by the form with single backslashes before any char and this is what is removed while doing "quote removal".
BTW: the variable expansion:
abc=123
done with
command "$abc"
results in
command 123
before quote removal is done.
command $abc
results in
command 123
before quote removal is done.
The answer is simple, the line:
echo $va
does not contain quotes that need to be removed.
This is how the shell has been defined since more than 40 years already. Note that the Bourne Shell first appeared AT&T internally in 1976.
BTW: "quoting" in this regard meant characters with the 8th bit on in the 1970s. So this in a shell internal form of quoting.
Since the Bourne Shell has been reworked to support 8-bit characters, in the mid 1980s, this internal form of quotuing has been replaced by backslashes in the internal strings before any quoted character.
Today, the Bourne Shell works the following way:
Strings that are written in single quotes are replaced by the backslash form. This e.g. means that 'abc' is replaced by abc
Strings with explicitely typed backslashes are kept internally.
Strings with double quotes keep their double quotes, so "abc" remains internally "abc"
When doing parameter expansion, the shell replaces all kind of quoted strings (see three forms above) by the form with single backslashes before any char and this is what is removed while doing "quote removal".
BTW: the variable expansion:
abc=123
done with
command "$abc"
results in
command 123
before quote removal is done.
command $abc
results in
command 123
before quote removal is done.
edited 2 days ago
answered 2 days ago
schily
10.5k31640
10.5k31640
add a comment |
add a comment |
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f481587%2fwhy-does-bash-not-remove-backslash-in-the-quote-removal-step-in-this-example%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
I think you are forgetting that using ' takes out the meaning of what follows ahead.
– Rui F Ribeiro
2 days ago
I am asking about
echo $va
, where there is no single quote stored in$va
or involved in any way.– Tim
2 days ago
1
@Tim Quote and escape parsing, removal, etc all happen before variable references are expanded. The only port-processing done on (non-quoted) variable expansions is word splitting and wildcard expansion.
– Gordon Davisson
2 days ago