Define variable using read from stdin of heredoc












1















I am trying to store Available and Total Memory into variables in a script file as follows,



read -r Available Total <<EOT
$(free -m | awk '/^Mem/{print $7; print $2;}')
EOT

$ echo $Total

$ echo $Available
1437


But I am unable to store the variable $Total.



But when I do:



$ read Available Total <<EOT
$(echo $(free -m | awk '/^Mem/{print $7; print $2;}'))
EOT

$ echo $Available
1309
$ echo $Total
7865


It works. But shellcheck gives me following suggestion:



Useless echo? Instead of 'echo $(cmd)', just use 'cmd'. [SC2005]



Why the forst example didn't work? and Why the second one works?










share|improve this question



























    1















    I am trying to store Available and Total Memory into variables in a script file as follows,



    read -r Available Total <<EOT
    $(free -m | awk '/^Mem/{print $7; print $2;}')
    EOT

    $ echo $Total

    $ echo $Available
    1437


    But I am unable to store the variable $Total.



    But when I do:



    $ read Available Total <<EOT
    $(echo $(free -m | awk '/^Mem/{print $7; print $2;}'))
    EOT

    $ echo $Available
    1309
    $ echo $Total
    7865


    It works. But shellcheck gives me following suggestion:



    Useless echo? Instead of 'echo $(cmd)', just use 'cmd'. [SC2005]



    Why the forst example didn't work? and Why the second one works?










    share|improve this question

























      1












      1








      1








      I am trying to store Available and Total Memory into variables in a script file as follows,



      read -r Available Total <<EOT
      $(free -m | awk '/^Mem/{print $7; print $2;}')
      EOT

      $ echo $Total

      $ echo $Available
      1437


      But I am unable to store the variable $Total.



      But when I do:



      $ read Available Total <<EOT
      $(echo $(free -m | awk '/^Mem/{print $7; print $2;}'))
      EOT

      $ echo $Available
      1309
      $ echo $Total
      7865


      It works. But shellcheck gives me following suggestion:



      Useless echo? Instead of 'echo $(cmd)', just use 'cmd'. [SC2005]



      Why the forst example didn't work? and Why the second one works?










      share|improve this question














      I am trying to store Available and Total Memory into variables in a script file as follows,



      read -r Available Total <<EOT
      $(free -m | awk '/^Mem/{print $7; print $2;}')
      EOT

      $ echo $Total

      $ echo $Available
      1437


      But I am unable to store the variable $Total.



      But when I do:



      $ read Available Total <<EOT
      $(echo $(free -m | awk '/^Mem/{print $7; print $2;}'))
      EOT

      $ echo $Available
      1309
      $ echo $Total
      7865


      It works. But shellcheck gives me following suggestion:



      Useless echo? Instead of 'echo $(cmd)', just use 'cmd'. [SC2005]



      Why the forst example didn't work? and Why the second one works?







      bash variable echo here-document shellcheck






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked 2 days ago









      NikhilNikhil

      256110




      256110






















          1 Answer
          1






          active

          oldest

          votes


















          4














          That awk command prints the two values on two separate lines, while read reads one line, expecting to find two fields on it.



          Change the print command to print $7, $2; to print the numbers on the same line. Since you tagged this with Bash, you can use a here-string instead of a here-doc to make the full command a bit neater:



          $ read -r Available Total <<< $( free -m | awk '/^Mem/{print $7, $2;}' )


          Or use a process substitution:



          $ read -r Available Total <   <( free -m | awk '/^Mem/{print $7, $2;}' )




          If you use echo $(...) without quotes around the command substitution, the output from the command gets word-split, and echo sees the separate lines as separate arguments. It prints all of its arguments joined with spaces, so on a single line.



          echo $(foo) is usually rather a useless thing to do, but isn't the same same just foo, for this very reason. It also puts a final newline at the end of the output of foo, if it wasn't there already.






          share|improve this answer





















          • 1





            Process Substitution would work here as well.

            – glenn jackman
            2 days ago











          • @glennjackman This doesn't work read -r Available Total <(free -m | awk '/^Mem/{print $7, $2;}') Could you please correct this?

            – Nikhil
            2 days ago






          • 2





            @Nikhil, process substitution needs the redirection operator < here. In itself it just expands to a (pseudo)filename, which read would take as the name of a variable to write to. (It's probably something like /dev/fd/63, which isn't a valid variable name so you get an error.)

            – ilkkachu
            2 days ago








          • 1





            Yes, read reads stdin, so you need a redirection.

            – glenn jackman
            2 days ago











          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',
          autoActivateHeartbeat: false,
          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%2f494241%2fdefine-variable-using-read-from-stdin-of-heredoc%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          4














          That awk command prints the two values on two separate lines, while read reads one line, expecting to find two fields on it.



          Change the print command to print $7, $2; to print the numbers on the same line. Since you tagged this with Bash, you can use a here-string instead of a here-doc to make the full command a bit neater:



          $ read -r Available Total <<< $( free -m | awk '/^Mem/{print $7, $2;}' )


          Or use a process substitution:



          $ read -r Available Total <   <( free -m | awk '/^Mem/{print $7, $2;}' )




          If you use echo $(...) without quotes around the command substitution, the output from the command gets word-split, and echo sees the separate lines as separate arguments. It prints all of its arguments joined with spaces, so on a single line.



          echo $(foo) is usually rather a useless thing to do, but isn't the same same just foo, for this very reason. It also puts a final newline at the end of the output of foo, if it wasn't there already.






          share|improve this answer





















          • 1





            Process Substitution would work here as well.

            – glenn jackman
            2 days ago











          • @glennjackman This doesn't work read -r Available Total <(free -m | awk '/^Mem/{print $7, $2;}') Could you please correct this?

            – Nikhil
            2 days ago






          • 2





            @Nikhil, process substitution needs the redirection operator < here. In itself it just expands to a (pseudo)filename, which read would take as the name of a variable to write to. (It's probably something like /dev/fd/63, which isn't a valid variable name so you get an error.)

            – ilkkachu
            2 days ago








          • 1





            Yes, read reads stdin, so you need a redirection.

            – glenn jackman
            2 days ago
















          4














          That awk command prints the two values on two separate lines, while read reads one line, expecting to find two fields on it.



          Change the print command to print $7, $2; to print the numbers on the same line. Since you tagged this with Bash, you can use a here-string instead of a here-doc to make the full command a bit neater:



          $ read -r Available Total <<< $( free -m | awk '/^Mem/{print $7, $2;}' )


          Or use a process substitution:



          $ read -r Available Total <   <( free -m | awk '/^Mem/{print $7, $2;}' )




          If you use echo $(...) without quotes around the command substitution, the output from the command gets word-split, and echo sees the separate lines as separate arguments. It prints all of its arguments joined with spaces, so on a single line.



          echo $(foo) is usually rather a useless thing to do, but isn't the same same just foo, for this very reason. It also puts a final newline at the end of the output of foo, if it wasn't there already.






          share|improve this answer





















          • 1





            Process Substitution would work here as well.

            – glenn jackman
            2 days ago











          • @glennjackman This doesn't work read -r Available Total <(free -m | awk '/^Mem/{print $7, $2;}') Could you please correct this?

            – Nikhil
            2 days ago






          • 2





            @Nikhil, process substitution needs the redirection operator < here. In itself it just expands to a (pseudo)filename, which read would take as the name of a variable to write to. (It's probably something like /dev/fd/63, which isn't a valid variable name so you get an error.)

            – ilkkachu
            2 days ago








          • 1





            Yes, read reads stdin, so you need a redirection.

            – glenn jackman
            2 days ago














          4












          4








          4







          That awk command prints the two values on two separate lines, while read reads one line, expecting to find two fields on it.



          Change the print command to print $7, $2; to print the numbers on the same line. Since you tagged this with Bash, you can use a here-string instead of a here-doc to make the full command a bit neater:



          $ read -r Available Total <<< $( free -m | awk '/^Mem/{print $7, $2;}' )


          Or use a process substitution:



          $ read -r Available Total <   <( free -m | awk '/^Mem/{print $7, $2;}' )




          If you use echo $(...) without quotes around the command substitution, the output from the command gets word-split, and echo sees the separate lines as separate arguments. It prints all of its arguments joined with spaces, so on a single line.



          echo $(foo) is usually rather a useless thing to do, but isn't the same same just foo, for this very reason. It also puts a final newline at the end of the output of foo, if it wasn't there already.






          share|improve this answer















          That awk command prints the two values on two separate lines, while read reads one line, expecting to find two fields on it.



          Change the print command to print $7, $2; to print the numbers on the same line. Since you tagged this with Bash, you can use a here-string instead of a here-doc to make the full command a bit neater:



          $ read -r Available Total <<< $( free -m | awk '/^Mem/{print $7, $2;}' )


          Or use a process substitution:



          $ read -r Available Total <   <( free -m | awk '/^Mem/{print $7, $2;}' )




          If you use echo $(...) without quotes around the command substitution, the output from the command gets word-split, and echo sees the separate lines as separate arguments. It prints all of its arguments joined with spaces, so on a single line.



          echo $(foo) is usually rather a useless thing to do, but isn't the same same just foo, for this very reason. It also puts a final newline at the end of the output of foo, if it wasn't there already.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited 2 days ago

























          answered 2 days ago









          ilkkachuilkkachu

          56.6k784156




          56.6k784156








          • 1





            Process Substitution would work here as well.

            – glenn jackman
            2 days ago











          • @glennjackman This doesn't work read -r Available Total <(free -m | awk '/^Mem/{print $7, $2;}') Could you please correct this?

            – Nikhil
            2 days ago






          • 2





            @Nikhil, process substitution needs the redirection operator < here. In itself it just expands to a (pseudo)filename, which read would take as the name of a variable to write to. (It's probably something like /dev/fd/63, which isn't a valid variable name so you get an error.)

            – ilkkachu
            2 days ago








          • 1





            Yes, read reads stdin, so you need a redirection.

            – glenn jackman
            2 days ago














          • 1





            Process Substitution would work here as well.

            – glenn jackman
            2 days ago











          • @glennjackman This doesn't work read -r Available Total <(free -m | awk '/^Mem/{print $7, $2;}') Could you please correct this?

            – Nikhil
            2 days ago






          • 2





            @Nikhil, process substitution needs the redirection operator < here. In itself it just expands to a (pseudo)filename, which read would take as the name of a variable to write to. (It's probably something like /dev/fd/63, which isn't a valid variable name so you get an error.)

            – ilkkachu
            2 days ago








          • 1





            Yes, read reads stdin, so you need a redirection.

            – glenn jackman
            2 days ago








          1




          1





          Process Substitution would work here as well.

          – glenn jackman
          2 days ago





          Process Substitution would work here as well.

          – glenn jackman
          2 days ago













          @glennjackman This doesn't work read -r Available Total <(free -m | awk '/^Mem/{print $7, $2;}') Could you please correct this?

          – Nikhil
          2 days ago





          @glennjackman This doesn't work read -r Available Total <(free -m | awk '/^Mem/{print $7, $2;}') Could you please correct this?

          – Nikhil
          2 days ago




          2




          2





          @Nikhil, process substitution needs the redirection operator < here. In itself it just expands to a (pseudo)filename, which read would take as the name of a variable to write to. (It's probably something like /dev/fd/63, which isn't a valid variable name so you get an error.)

          – ilkkachu
          2 days ago







          @Nikhil, process substitution needs the redirection operator < here. In itself it just expands to a (pseudo)filename, which read would take as the name of a variable to write to. (It's probably something like /dev/fd/63, which isn't a valid variable name so you get an error.)

          – ilkkachu
          2 days ago






          1




          1





          Yes, read reads stdin, so you need a redirection.

          – glenn jackman
          2 days ago





          Yes, read reads stdin, so you need a redirection.

          – glenn jackman
          2 days ago


















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Unix & Linux Stack Exchange!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f494241%2fdefine-variable-using-read-from-stdin-of-heredoc%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

          "Incorrect syntax near the keyword 'ON'. (on update cascade, on delete cascade,)

          Alcedinidae

          RAC Tourist Trophy