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.










share|improve this question




















  • 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















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.










share|improve this question




















  • 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













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.










share|improve this question















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






share|improve this question















share|improve this question













share|improve this question




share|improve this question








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 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














  • 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








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










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.






share|improve this answer




























    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.






    share|improve this answer





















    • Thanks. ........................
      – Tim
      2 days ago


















    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.






    share|improve this answer























      Your Answer








      StackExchange.ready(function() {
      var channelOptions = {
      tags: "".split(" "),
      id: "106"
      };
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function() {
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled) {
      StackExchange.using("snippets", function() {
      createEditor();
      });
      }
      else {
      createEditor();
      }
      });

      function createEditor() {
      StackExchange.prepareEditor({
      heartbeatType: 'answer',
      convertImagesToLinks: false,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: null,
      bindNavPrevention: true,
      postfix: "",
      imageUploader: {
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      },
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      });


      }
      });














       

      draft saved


      draft discarded


















      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

























      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.






      share|improve this answer

























        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.






        share|improve this answer























          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.






          share|improve this answer












          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.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered 2 days ago









          Wumpus Q. Wumbley

          4,5901322




          4,5901322
























              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.






              share|improve this answer





















              • Thanks. ........................
                – Tim
                2 days ago















              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.






              share|improve this answer





















              • Thanks. ........................
                – Tim
                2 days ago













              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.






              share|improve this answer













              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.







              share|improve this answer












              share|improve this answer



              share|improve this answer










              answered 2 days ago









              muru

              34.7k580153




              34.7k580153












              • Thanks. ........................
                – Tim
                2 days ago


















              • Thanks. ........................
                – Tim
                2 days ago
















              Thanks. ........................
              – Tim
              2 days ago




              Thanks. ........................
              – Tim
              2 days ago










              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.






              share|improve this answer



























                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.






                share|improve this answer

























                  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.






                  share|improve this answer














                  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.







                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited 2 days ago

























                  answered 2 days ago









                  schily

                  10.5k31640




                  10.5k31640






























                       

                      draft saved


                      draft discarded



















































                       


                      draft saved


                      draft discarded














                      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





















































                      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







                      Popular posts from this blog

                      Morgemoulin

                      Scott Moir

                      Souastre