How to get values after an equal sign












2















I have a file delimited with space and random column ordering as follows:



name=Joan age=42 ip=172.20.1.80 sex=M loc=UK 
loc=IR sex=F ip=172.20.1.1 age=32 name=Sandra


I want to extract specific fields (name, loc, and ip) only.



So the result that I'm looking for is as follows:



Joan|UK|172.20.1.80
Sandra|IR|172.20.1.1









share|improve this question

























  • Similar (if you just replace the space with newline), stackoverflow.com/questions/16571739/…

    – michael
    Jan 27 at 13:04











  • @michael Not quite. You need something to detect the different "blocks" then if the input has more that one line.

    – PerlDuck
    Jan 27 at 13:12
















2















I have a file delimited with space and random column ordering as follows:



name=Joan age=42 ip=172.20.1.80 sex=M loc=UK 
loc=IR sex=F ip=172.20.1.1 age=32 name=Sandra


I want to extract specific fields (name, loc, and ip) only.



So the result that I'm looking for is as follows:



Joan|UK|172.20.1.80
Sandra|IR|172.20.1.1









share|improve this question

























  • Similar (if you just replace the space with newline), stackoverflow.com/questions/16571739/…

    – michael
    Jan 27 at 13:04











  • @michael Not quite. You need something to detect the different "blocks" then if the input has more that one line.

    – PerlDuck
    Jan 27 at 13:12














2












2








2








I have a file delimited with space and random column ordering as follows:



name=Joan age=42 ip=172.20.1.80 sex=M loc=UK 
loc=IR sex=F ip=172.20.1.1 age=32 name=Sandra


I want to extract specific fields (name, loc, and ip) only.



So the result that I'm looking for is as follows:



Joan|UK|172.20.1.80
Sandra|IR|172.20.1.1









share|improve this question
















I have a file delimited with space and random column ordering as follows:



name=Joan age=42 ip=172.20.1.80 sex=M loc=UK 
loc=IR sex=F ip=172.20.1.1 age=32 name=Sandra


I want to extract specific fields (name, loc, and ip) only.



So the result that I'm looking for is as follows:



Joan|UK|172.20.1.80
Sandra|IR|172.20.1.1






bash text-processing






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Jan 27 at 20:34









Peter Mortensen

1,03721016




1,03721016










asked Jan 27 at 11:32









Ubai salihUbai salih

253




253













  • Similar (if you just replace the space with newline), stackoverflow.com/questions/16571739/…

    – michael
    Jan 27 at 13:04











  • @michael Not quite. You need something to detect the different "blocks" then if the input has more that one line.

    – PerlDuck
    Jan 27 at 13:12



















  • Similar (if you just replace the space with newline), stackoverflow.com/questions/16571739/…

    – michael
    Jan 27 at 13:04











  • @michael Not quite. You need something to detect the different "blocks" then if the input has more that one line.

    – PerlDuck
    Jan 27 at 13:12

















Similar (if you just replace the space with newline), stackoverflow.com/questions/16571739/…

– michael
Jan 27 at 13:04





Similar (if you just replace the space with newline), stackoverflow.com/questions/16571739/…

– michael
Jan 27 at 13:04













@michael Not quite. You need something to detect the different "blocks" then if the input has more that one line.

– PerlDuck
Jan 27 at 13:12





@michael Not quite. You need something to detect the different "blocks" then if the input has more that one line.

– PerlDuck
Jan 27 at 13:12










3 Answers
3






active

oldest

votes


















4














Luckily, your input file has a format the shell understands when it comes to
assigning variables a value: var1=value1 var2=value2 etc. So we can simply
read each line and use the eval command to evaluate the line.



Put the following into a file, say parse.sh, do chmod +x parse.sh and
run it with your input file as a parameter.



Script parse.sh:



#!/usr/bin/env bash

while read line; do
eval $line;
echo "$name|$loc|$ip"
done < "$1"

exit 0;


File input.txt:



name=Joan age=42 ip=172.20.1.80 sex=M loc=UK
loc=IR sex=F ip=172.20.1.1 age=32 name=Sandra


Run:



me@ubuntu:~> ./parse.sh input.txt 
Joan|UK|172.20.1.80
Sandra|IR|172.20.1.1




Please note that the values must not have a space in them. E.g.



ip=... name=Ubai salih loc=...


would not work and give syntax errors. Also, if the input file would contain a line with a bad_command that command gets executed because that is how eval works: it just executes the given string.






share|improve this answer


























  • just awesome , thank you very much

    – Ubai salih
    Jan 27 at 12:57






  • 2





    Die to the risk if code injection (malicious or accidentally), I might prefer a different solution.

    – michael
    Jan 27 at 13:06






  • 1





    @michael Yes, you are right. I added a note to the answer to mention that. Another possibility would be to split at spaces and then at =. Or pick name=S+ etc. with a regex. Feel invited to post another approach ;-)

    – PerlDuck
    Jan 27 at 13:09








  • 1





    @michael *Due to the risk *of ... Too late to edit the comment I know, but just wanted to mention the typos in case anyone else is confused.

    – wjandrea
    Jan 27 at 21:16













  • Oh goodness, sorry, I just noticed the typo (I blame autocorrect). Code injection is bad, but only on rare occasion lethal.

    – michael
    Jan 28 at 14:15



















1














FWIW, here's a Python solution like PerlDuck's Bash solution, but not evaluating the input.



#!/usr/bin/env python3

import fileinput

for line in fileinput.input():
record = line.rstrip('n')
d = dict(kv.split('=') for kv in record.split(' '))
print(d['name'], d['loc'], d['ip'], sep='|')


Run:



$ ./parse.py input.txt
Joan|UK|172.20.1.80
Sandra|IR|172.20.1.1





share|improve this answer

































    0














    Since the output order that you want is reverse lexical (name > loc > ip) you could select and then reverse sort the fields, then remove the fieldname= prefixes. For example in Perl:



    $ perl -alne '
    print join "|", map { s/.*=//r } reverse sort grep { /^(name|loc|ip)=/ } @F
    ' file
    Joan|UK|172.20.1.80
    Sandra|IR|172.20.1.1





    share|improve this answer























      Your Answer








      StackExchange.ready(function() {
      var channelOptions = {
      tags: "".split(" "),
      id: "89"
      };
      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: true,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      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%2faskubuntu.com%2fquestions%2f1113249%2fhow-to-get-values-after-an-equal-sign%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









      4














      Luckily, your input file has a format the shell understands when it comes to
      assigning variables a value: var1=value1 var2=value2 etc. So we can simply
      read each line and use the eval command to evaluate the line.



      Put the following into a file, say parse.sh, do chmod +x parse.sh and
      run it with your input file as a parameter.



      Script parse.sh:



      #!/usr/bin/env bash

      while read line; do
      eval $line;
      echo "$name|$loc|$ip"
      done < "$1"

      exit 0;


      File input.txt:



      name=Joan age=42 ip=172.20.1.80 sex=M loc=UK
      loc=IR sex=F ip=172.20.1.1 age=32 name=Sandra


      Run:



      me@ubuntu:~> ./parse.sh input.txt 
      Joan|UK|172.20.1.80
      Sandra|IR|172.20.1.1




      Please note that the values must not have a space in them. E.g.



      ip=... name=Ubai salih loc=...


      would not work and give syntax errors. Also, if the input file would contain a line with a bad_command that command gets executed because that is how eval works: it just executes the given string.






      share|improve this answer


























      • just awesome , thank you very much

        – Ubai salih
        Jan 27 at 12:57






      • 2





        Die to the risk if code injection (malicious or accidentally), I might prefer a different solution.

        – michael
        Jan 27 at 13:06






      • 1





        @michael Yes, you are right. I added a note to the answer to mention that. Another possibility would be to split at spaces and then at =. Or pick name=S+ etc. with a regex. Feel invited to post another approach ;-)

        – PerlDuck
        Jan 27 at 13:09








      • 1





        @michael *Due to the risk *of ... Too late to edit the comment I know, but just wanted to mention the typos in case anyone else is confused.

        – wjandrea
        Jan 27 at 21:16













      • Oh goodness, sorry, I just noticed the typo (I blame autocorrect). Code injection is bad, but only on rare occasion lethal.

        – michael
        Jan 28 at 14:15
















      4














      Luckily, your input file has a format the shell understands when it comes to
      assigning variables a value: var1=value1 var2=value2 etc. So we can simply
      read each line and use the eval command to evaluate the line.



      Put the following into a file, say parse.sh, do chmod +x parse.sh and
      run it with your input file as a parameter.



      Script parse.sh:



      #!/usr/bin/env bash

      while read line; do
      eval $line;
      echo "$name|$loc|$ip"
      done < "$1"

      exit 0;


      File input.txt:



      name=Joan age=42 ip=172.20.1.80 sex=M loc=UK
      loc=IR sex=F ip=172.20.1.1 age=32 name=Sandra


      Run:



      me@ubuntu:~> ./parse.sh input.txt 
      Joan|UK|172.20.1.80
      Sandra|IR|172.20.1.1




      Please note that the values must not have a space in them. E.g.



      ip=... name=Ubai salih loc=...


      would not work and give syntax errors. Also, if the input file would contain a line with a bad_command that command gets executed because that is how eval works: it just executes the given string.






      share|improve this answer


























      • just awesome , thank you very much

        – Ubai salih
        Jan 27 at 12:57






      • 2





        Die to the risk if code injection (malicious or accidentally), I might prefer a different solution.

        – michael
        Jan 27 at 13:06






      • 1





        @michael Yes, you are right. I added a note to the answer to mention that. Another possibility would be to split at spaces and then at =. Or pick name=S+ etc. with a regex. Feel invited to post another approach ;-)

        – PerlDuck
        Jan 27 at 13:09








      • 1





        @michael *Due to the risk *of ... Too late to edit the comment I know, but just wanted to mention the typos in case anyone else is confused.

        – wjandrea
        Jan 27 at 21:16













      • Oh goodness, sorry, I just noticed the typo (I blame autocorrect). Code injection is bad, but only on rare occasion lethal.

        – michael
        Jan 28 at 14:15














      4












      4








      4







      Luckily, your input file has a format the shell understands when it comes to
      assigning variables a value: var1=value1 var2=value2 etc. So we can simply
      read each line and use the eval command to evaluate the line.



      Put the following into a file, say parse.sh, do chmod +x parse.sh and
      run it with your input file as a parameter.



      Script parse.sh:



      #!/usr/bin/env bash

      while read line; do
      eval $line;
      echo "$name|$loc|$ip"
      done < "$1"

      exit 0;


      File input.txt:



      name=Joan age=42 ip=172.20.1.80 sex=M loc=UK
      loc=IR sex=F ip=172.20.1.1 age=32 name=Sandra


      Run:



      me@ubuntu:~> ./parse.sh input.txt 
      Joan|UK|172.20.1.80
      Sandra|IR|172.20.1.1




      Please note that the values must not have a space in them. E.g.



      ip=... name=Ubai salih loc=...


      would not work and give syntax errors. Also, if the input file would contain a line with a bad_command that command gets executed because that is how eval works: it just executes the given string.






      share|improve this answer















      Luckily, your input file has a format the shell understands when it comes to
      assigning variables a value: var1=value1 var2=value2 etc. So we can simply
      read each line and use the eval command to evaluate the line.



      Put the following into a file, say parse.sh, do chmod +x parse.sh and
      run it with your input file as a parameter.



      Script parse.sh:



      #!/usr/bin/env bash

      while read line; do
      eval $line;
      echo "$name|$loc|$ip"
      done < "$1"

      exit 0;


      File input.txt:



      name=Joan age=42 ip=172.20.1.80 sex=M loc=UK
      loc=IR sex=F ip=172.20.1.1 age=32 name=Sandra


      Run:



      me@ubuntu:~> ./parse.sh input.txt 
      Joan|UK|172.20.1.80
      Sandra|IR|172.20.1.1




      Please note that the values must not have a space in them. E.g.



      ip=... name=Ubai salih loc=...


      would not work and give syntax errors. Also, if the input file would contain a line with a bad_command that command gets executed because that is how eval works: it just executes the given string.







      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited Jan 27 at 13:06

























      answered Jan 27 at 12:17









      PerlDuckPerlDuck

      6,73711535




      6,73711535













      • just awesome , thank you very much

        – Ubai salih
        Jan 27 at 12:57






      • 2





        Die to the risk if code injection (malicious or accidentally), I might prefer a different solution.

        – michael
        Jan 27 at 13:06






      • 1





        @michael Yes, you are right. I added a note to the answer to mention that. Another possibility would be to split at spaces and then at =. Or pick name=S+ etc. with a regex. Feel invited to post another approach ;-)

        – PerlDuck
        Jan 27 at 13:09








      • 1





        @michael *Due to the risk *of ... Too late to edit the comment I know, but just wanted to mention the typos in case anyone else is confused.

        – wjandrea
        Jan 27 at 21:16













      • Oh goodness, sorry, I just noticed the typo (I blame autocorrect). Code injection is bad, but only on rare occasion lethal.

        – michael
        Jan 28 at 14:15



















      • just awesome , thank you very much

        – Ubai salih
        Jan 27 at 12:57






      • 2





        Die to the risk if code injection (malicious or accidentally), I might prefer a different solution.

        – michael
        Jan 27 at 13:06






      • 1





        @michael Yes, you are right. I added a note to the answer to mention that. Another possibility would be to split at spaces and then at =. Or pick name=S+ etc. with a regex. Feel invited to post another approach ;-)

        – PerlDuck
        Jan 27 at 13:09








      • 1





        @michael *Due to the risk *of ... Too late to edit the comment I know, but just wanted to mention the typos in case anyone else is confused.

        – wjandrea
        Jan 27 at 21:16













      • Oh goodness, sorry, I just noticed the typo (I blame autocorrect). Code injection is bad, but only on rare occasion lethal.

        – michael
        Jan 28 at 14:15

















      just awesome , thank you very much

      – Ubai salih
      Jan 27 at 12:57





      just awesome , thank you very much

      – Ubai salih
      Jan 27 at 12:57




      2




      2





      Die to the risk if code injection (malicious or accidentally), I might prefer a different solution.

      – michael
      Jan 27 at 13:06





      Die to the risk if code injection (malicious or accidentally), I might prefer a different solution.

      – michael
      Jan 27 at 13:06




      1




      1





      @michael Yes, you are right. I added a note to the answer to mention that. Another possibility would be to split at spaces and then at =. Or pick name=S+ etc. with a regex. Feel invited to post another approach ;-)

      – PerlDuck
      Jan 27 at 13:09







      @michael Yes, you are right. I added a note to the answer to mention that. Another possibility would be to split at spaces and then at =. Or pick name=S+ etc. with a regex. Feel invited to post another approach ;-)

      – PerlDuck
      Jan 27 at 13:09






      1




      1





      @michael *Due to the risk *of ... Too late to edit the comment I know, but just wanted to mention the typos in case anyone else is confused.

      – wjandrea
      Jan 27 at 21:16







      @michael *Due to the risk *of ... Too late to edit the comment I know, but just wanted to mention the typos in case anyone else is confused.

      – wjandrea
      Jan 27 at 21:16















      Oh goodness, sorry, I just noticed the typo (I blame autocorrect). Code injection is bad, but only on rare occasion lethal.

      – michael
      Jan 28 at 14:15





      Oh goodness, sorry, I just noticed the typo (I blame autocorrect). Code injection is bad, but only on rare occasion lethal.

      – michael
      Jan 28 at 14:15













      1














      FWIW, here's a Python solution like PerlDuck's Bash solution, but not evaluating the input.



      #!/usr/bin/env python3

      import fileinput

      for line in fileinput.input():
      record = line.rstrip('n')
      d = dict(kv.split('=') for kv in record.split(' '))
      print(d['name'], d['loc'], d['ip'], sep='|')


      Run:



      $ ./parse.py input.txt
      Joan|UK|172.20.1.80
      Sandra|IR|172.20.1.1





      share|improve this answer






























        1














        FWIW, here's a Python solution like PerlDuck's Bash solution, but not evaluating the input.



        #!/usr/bin/env python3

        import fileinput

        for line in fileinput.input():
        record = line.rstrip('n')
        d = dict(kv.split('=') for kv in record.split(' '))
        print(d['name'], d['loc'], d['ip'], sep='|')


        Run:



        $ ./parse.py input.txt
        Joan|UK|172.20.1.80
        Sandra|IR|172.20.1.1





        share|improve this answer




























          1












          1








          1







          FWIW, here's a Python solution like PerlDuck's Bash solution, but not evaluating the input.



          #!/usr/bin/env python3

          import fileinput

          for line in fileinput.input():
          record = line.rstrip('n')
          d = dict(kv.split('=') for kv in record.split(' '))
          print(d['name'], d['loc'], d['ip'], sep='|')


          Run:



          $ ./parse.py input.txt
          Joan|UK|172.20.1.80
          Sandra|IR|172.20.1.1





          share|improve this answer















          FWIW, here's a Python solution like PerlDuck's Bash solution, but not evaluating the input.



          #!/usr/bin/env python3

          import fileinput

          for line in fileinput.input():
          record = line.rstrip('n')
          d = dict(kv.split('=') for kv in record.split(' '))
          print(d['name'], d['loc'], d['ip'], sep='|')


          Run:



          $ ./parse.py input.txt
          Joan|UK|172.20.1.80
          Sandra|IR|172.20.1.1






          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Feb 1 at 14:26

























          answered Jan 27 at 23:05









          wjandreawjandrea

          9,21442363




          9,21442363























              0














              Since the output order that you want is reverse lexical (name > loc > ip) you could select and then reverse sort the fields, then remove the fieldname= prefixes. For example in Perl:



              $ perl -alne '
              print join "|", map { s/.*=//r } reverse sort grep { /^(name|loc|ip)=/ } @F
              ' file
              Joan|UK|172.20.1.80
              Sandra|IR|172.20.1.1





              share|improve this answer




























                0














                Since the output order that you want is reverse lexical (name > loc > ip) you could select and then reverse sort the fields, then remove the fieldname= prefixes. For example in Perl:



                $ perl -alne '
                print join "|", map { s/.*=//r } reverse sort grep { /^(name|loc|ip)=/ } @F
                ' file
                Joan|UK|172.20.1.80
                Sandra|IR|172.20.1.1





                share|improve this answer


























                  0












                  0








                  0







                  Since the output order that you want is reverse lexical (name > loc > ip) you could select and then reverse sort the fields, then remove the fieldname= prefixes. For example in Perl:



                  $ perl -alne '
                  print join "|", map { s/.*=//r } reverse sort grep { /^(name|loc|ip)=/ } @F
                  ' file
                  Joan|UK|172.20.1.80
                  Sandra|IR|172.20.1.1





                  share|improve this answer













                  Since the output order that you want is reverse lexical (name > loc > ip) you could select and then reverse sort the fields, then remove the fieldname= prefixes. For example in Perl:



                  $ perl -alne '
                  print join "|", map { s/.*=//r } reverse sort grep { /^(name|loc|ip)=/ } @F
                  ' file
                  Joan|UK|172.20.1.80
                  Sandra|IR|172.20.1.1






                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Jan 27 at 12:49









                  steeldriversteeldriver

                  68k11111182




                  68k11111182






























                      draft saved

                      draft discarded




















































                      Thanks for contributing an answer to Ask Ubuntu!


                      • 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%2faskubuntu.com%2fquestions%2f1113249%2fhow-to-get-values-after-an-equal-sign%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

                      flock() on closed filehandle LOCK_FILE at /usr/bin/apt-mirror

                      Mangá

                       ⁒  ․,‪⁊‑⁙ ⁖, ⁇‒※‌, †,⁖‗‌⁝    ‾‸⁘,‖⁔⁣,⁂‾
”‑,‥–,‬ ,⁀‹⁋‴⁑ ‒ ,‴⁋”‼ ⁨,‷⁔„ ‰′,‐‚ ‥‡‎“‷⁃⁨⁅⁣,⁔
⁇‘⁔⁡⁏⁌⁡‿‶‏⁨ ⁣⁕⁖⁨⁩⁥‽⁀  ‴‬⁜‟ ⁃‣‧⁕‮ …‍⁨‴ ⁩,⁚⁖‫ ,‵ ⁀,‮⁝‣‣ ⁑  ⁂– ․, ‾‽ ‏⁁“⁗‸ ‾… ‹‡⁌⁎‸‘ ‡⁏⁌‪ ‵⁛ ‎⁨ ―⁦⁤⁄⁕