Extract multiple lines if match












4















I have a command that outputs information about all DIMM slots in blocks like the following:



ID    SIZE TYPE
44 105 SMB_TYPE_MEMDEVICE (type 17) (memory device)

Manufacturer: NO DIMM
Serial Number: NO DIMM
Asset Tag: NO DIMM
Location Tag: P1-DIMMD1
Part Number: NO DIMM

Physical Memory Array: 43
Memory Error Data: Not Supported
Total Width: 0 bits
Data Width: 0 bits
Size: Not Populated
Form Factor: 9 (DIMM)
Set: None
Rank: Unknown
Memory Type: 2 (unknown)
Flags: 0x4
SMB_MDF_UNKNOWN (unknown)
Speed: Unknown
Configured Speed: Unknown
Device Locator: P1-DIMMD1
Bank Locator: P0_Node1_Channel0_Dimm0
Minimum Voltage: 1.20V
Maximum Voltage: 1.20V
Configured Voltage: 1.20V


The blocks start with the ID SIZE TYPE header and end with the configured voltage information. The command outputs one of these blocks of data for each DIMM separated by a single blank line each.





I would like to be able to get the block of information for a specific DIMM slot based on the Location Tag field, but am unsure how to go about it. I am pretty sure this can be done with awk but only know how to print the match awk '/P1-DIMMD1/' or the line prior to match awk '/P1-DIMMD1/ {print a}{a=$0}'



Does anyone know how I could extract this whole block of data if the Location Tag matches my search (P1-DIMMD1)?










share|improve this question



























    4















    I have a command that outputs information about all DIMM slots in blocks like the following:



    ID    SIZE TYPE
    44 105 SMB_TYPE_MEMDEVICE (type 17) (memory device)

    Manufacturer: NO DIMM
    Serial Number: NO DIMM
    Asset Tag: NO DIMM
    Location Tag: P1-DIMMD1
    Part Number: NO DIMM

    Physical Memory Array: 43
    Memory Error Data: Not Supported
    Total Width: 0 bits
    Data Width: 0 bits
    Size: Not Populated
    Form Factor: 9 (DIMM)
    Set: None
    Rank: Unknown
    Memory Type: 2 (unknown)
    Flags: 0x4
    SMB_MDF_UNKNOWN (unknown)
    Speed: Unknown
    Configured Speed: Unknown
    Device Locator: P1-DIMMD1
    Bank Locator: P0_Node1_Channel0_Dimm0
    Minimum Voltage: 1.20V
    Maximum Voltage: 1.20V
    Configured Voltage: 1.20V


    The blocks start with the ID SIZE TYPE header and end with the configured voltage information. The command outputs one of these blocks of data for each DIMM separated by a single blank line each.





    I would like to be able to get the block of information for a specific DIMM slot based on the Location Tag field, but am unsure how to go about it. I am pretty sure this can be done with awk but only know how to print the match awk '/P1-DIMMD1/' or the line prior to match awk '/P1-DIMMD1/ {print a}{a=$0}'



    Does anyone know how I could extract this whole block of data if the Location Tag matches my search (P1-DIMMD1)?










    share|improve this question

























      4












      4








      4


      0






      I have a command that outputs information about all DIMM slots in blocks like the following:



      ID    SIZE TYPE
      44 105 SMB_TYPE_MEMDEVICE (type 17) (memory device)

      Manufacturer: NO DIMM
      Serial Number: NO DIMM
      Asset Tag: NO DIMM
      Location Tag: P1-DIMMD1
      Part Number: NO DIMM

      Physical Memory Array: 43
      Memory Error Data: Not Supported
      Total Width: 0 bits
      Data Width: 0 bits
      Size: Not Populated
      Form Factor: 9 (DIMM)
      Set: None
      Rank: Unknown
      Memory Type: 2 (unknown)
      Flags: 0x4
      SMB_MDF_UNKNOWN (unknown)
      Speed: Unknown
      Configured Speed: Unknown
      Device Locator: P1-DIMMD1
      Bank Locator: P0_Node1_Channel0_Dimm0
      Minimum Voltage: 1.20V
      Maximum Voltage: 1.20V
      Configured Voltage: 1.20V


      The blocks start with the ID SIZE TYPE header and end with the configured voltage information. The command outputs one of these blocks of data for each DIMM separated by a single blank line each.





      I would like to be able to get the block of information for a specific DIMM slot based on the Location Tag field, but am unsure how to go about it. I am pretty sure this can be done with awk but only know how to print the match awk '/P1-DIMMD1/' or the line prior to match awk '/P1-DIMMD1/ {print a}{a=$0}'



      Does anyone know how I could extract this whole block of data if the Location Tag matches my search (P1-DIMMD1)?










      share|improve this question














      I have a command that outputs information about all DIMM slots in blocks like the following:



      ID    SIZE TYPE
      44 105 SMB_TYPE_MEMDEVICE (type 17) (memory device)

      Manufacturer: NO DIMM
      Serial Number: NO DIMM
      Asset Tag: NO DIMM
      Location Tag: P1-DIMMD1
      Part Number: NO DIMM

      Physical Memory Array: 43
      Memory Error Data: Not Supported
      Total Width: 0 bits
      Data Width: 0 bits
      Size: Not Populated
      Form Factor: 9 (DIMM)
      Set: None
      Rank: Unknown
      Memory Type: 2 (unknown)
      Flags: 0x4
      SMB_MDF_UNKNOWN (unknown)
      Speed: Unknown
      Configured Speed: Unknown
      Device Locator: P1-DIMMD1
      Bank Locator: P0_Node1_Channel0_Dimm0
      Minimum Voltage: 1.20V
      Maximum Voltage: 1.20V
      Configured Voltage: 1.20V


      The blocks start with the ID SIZE TYPE header and end with the configured voltage information. The command outputs one of these blocks of data for each DIMM separated by a single blank line each.





      I would like to be able to get the block of information for a specific DIMM slot based on the Location Tag field, but am unsure how to go about it. I am pretty sure this can be done with awk but only know how to print the match awk '/P1-DIMMD1/' or the line prior to match awk '/P1-DIMMD1/ {print a}{a=$0}'



      Does anyone know how I could extract this whole block of data if the Location Tag matches my search (P1-DIMMD1)?







      text-processing awk






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked 14 hours ago









      Jesse_bJesse_b

      12.1k23064




      12.1k23064






















          3 Answers
          3






          active

          oldest

          votes


















          6














          The following will match the tag given in the tag variable:



          awk -v tag=P1-DIMMD1 '/ID    SIZE TYPE/ { block = $0; output = 0; next } { block = block "n" $0 } /Location Tag/ { output = ($0 ~ tag) } /Configured Voltage/ && output { print block }'


          The AWK script is



          /ID    SIZE TYPE/ {
          block = $0
          output = 0
          next
          }

          { block = block "n" $0 }

          /Location Tag/ { output = ($0 ~ tag) }

          /Configured Voltage/ && output { print block }


          We accumulate a block in the block variable, and output it when we reach the end of the block if we saw the right tag in the process.






          share|improve this answer

































            4














            You could use ed ... and sed, man!



            You have to want to use ed for this one, though, as ed wants to operate on a file, not as part of a pipeline.




            1. command > dimm-output

            2. wanted=P1-DIMMD1

            3. ed -s dimm-output <<< $'/Location Tag: '"$wanted"$'n?^ID.*SIZE.*TYPEn.,/Configured Voltage/pnqn' | sed 1,2d


            The ed command-string breaks down to four n-separated commands:




            1. search forwards, using /, for the text "Location Tag: " followed by the value of the $wanted variable

            2. search backwards, using ?, for the pattern: (start-of-line), "ID", anything, "SIZE", anything, "TYPE"

            3. from that line (.), through (,) the next line that matches "Configured Voltage", print those lines (p)

            4. quit ed: q


            Because ed auto-prints the matching line when you search, I used sed here to delete those two lines.






            share|improve this answer































              2














              Inspired by @Stephen Kitts great answer, I wrote a little more general script to perform block matching when having a specified start and end pattern.



              #!/bin/sh

              [ -z "$4" ] && file="-" || file="$4"

              awk
              -v BLOCKSTART_PATTERN="$1"
              -v BLOCKEND_PATTERN="$2"
              -v BLOCKMATCH_PATTERN="$3"
              '
              $0 ~ BLOCKSTART_PATTERN { block = $0; output = 0; next }
              { block = block "n" $0 }
              $0 ~ BLOCKMATCH_PATTERN { output = 1 }
              $0 ~ BLOCKEND_PATTERN && output { print block; output = 0 }
              ' "$file"


              Usage: match_block START END MATCH [FILE].

              If file is omitted, stdin will be used.



              In your case:



              command | ./match_block '^ID' 'Configured Voltage' 'Location Tag: P1-DIMMD1'


              or



              ./match_block '^ID' 'Configured Voltage' 'Location Tag: P1-DIMMD1' file





              share|improve this answer
























              • You could even write this directly as an AWK script, instead of a shell script which calls AWK.

                – Stephen Kitt
                14 hours 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%2f495094%2fextract-multiple-lines-if-match%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









              6














              The following will match the tag given in the tag variable:



              awk -v tag=P1-DIMMD1 '/ID    SIZE TYPE/ { block = $0; output = 0; next } { block = block "n" $0 } /Location Tag/ { output = ($0 ~ tag) } /Configured Voltage/ && output { print block }'


              The AWK script is



              /ID    SIZE TYPE/ {
              block = $0
              output = 0
              next
              }

              { block = block "n" $0 }

              /Location Tag/ { output = ($0 ~ tag) }

              /Configured Voltage/ && output { print block }


              We accumulate a block in the block variable, and output it when we reach the end of the block if we saw the right tag in the process.






              share|improve this answer






























                6














                The following will match the tag given in the tag variable:



                awk -v tag=P1-DIMMD1 '/ID    SIZE TYPE/ { block = $0; output = 0; next } { block = block "n" $0 } /Location Tag/ { output = ($0 ~ tag) } /Configured Voltage/ && output { print block }'


                The AWK script is



                /ID    SIZE TYPE/ {
                block = $0
                output = 0
                next
                }

                { block = block "n" $0 }

                /Location Tag/ { output = ($0 ~ tag) }

                /Configured Voltage/ && output { print block }


                We accumulate a block in the block variable, and output it when we reach the end of the block if we saw the right tag in the process.






                share|improve this answer




























                  6












                  6








                  6







                  The following will match the tag given in the tag variable:



                  awk -v tag=P1-DIMMD1 '/ID    SIZE TYPE/ { block = $0; output = 0; next } { block = block "n" $0 } /Location Tag/ { output = ($0 ~ tag) } /Configured Voltage/ && output { print block }'


                  The AWK script is



                  /ID    SIZE TYPE/ {
                  block = $0
                  output = 0
                  next
                  }

                  { block = block "n" $0 }

                  /Location Tag/ { output = ($0 ~ tag) }

                  /Configured Voltage/ && output { print block }


                  We accumulate a block in the block variable, and output it when we reach the end of the block if we saw the right tag in the process.






                  share|improve this answer















                  The following will match the tag given in the tag variable:



                  awk -v tag=P1-DIMMD1 '/ID    SIZE TYPE/ { block = $0; output = 0; next } { block = block "n" $0 } /Location Tag/ { output = ($0 ~ tag) } /Configured Voltage/ && output { print block }'


                  The AWK script is



                  /ID    SIZE TYPE/ {
                  block = $0
                  output = 0
                  next
                  }

                  { block = block "n" $0 }

                  /Location Tag/ { output = ($0 ~ tag) }

                  /Configured Voltage/ && output { print block }


                  We accumulate a block in the block variable, and output it when we reach the end of the block if we saw the right tag in the process.







                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited 14 hours ago

























                  answered 14 hours ago









                  Stephen KittStephen Kitt

                  167k24376454




                  167k24376454

























                      4














                      You could use ed ... and sed, man!



                      You have to want to use ed for this one, though, as ed wants to operate on a file, not as part of a pipeline.




                      1. command > dimm-output

                      2. wanted=P1-DIMMD1

                      3. ed -s dimm-output <<< $'/Location Tag: '"$wanted"$'n?^ID.*SIZE.*TYPEn.,/Configured Voltage/pnqn' | sed 1,2d


                      The ed command-string breaks down to four n-separated commands:




                      1. search forwards, using /, for the text "Location Tag: " followed by the value of the $wanted variable

                      2. search backwards, using ?, for the pattern: (start-of-line), "ID", anything, "SIZE", anything, "TYPE"

                      3. from that line (.), through (,) the next line that matches "Configured Voltage", print those lines (p)

                      4. quit ed: q


                      Because ed auto-prints the matching line when you search, I used sed here to delete those two lines.






                      share|improve this answer




























                        4














                        You could use ed ... and sed, man!



                        You have to want to use ed for this one, though, as ed wants to operate on a file, not as part of a pipeline.




                        1. command > dimm-output

                        2. wanted=P1-DIMMD1

                        3. ed -s dimm-output <<< $'/Location Tag: '"$wanted"$'n?^ID.*SIZE.*TYPEn.,/Configured Voltage/pnqn' | sed 1,2d


                        The ed command-string breaks down to four n-separated commands:




                        1. search forwards, using /, for the text "Location Tag: " followed by the value of the $wanted variable

                        2. search backwards, using ?, for the pattern: (start-of-line), "ID", anything, "SIZE", anything, "TYPE"

                        3. from that line (.), through (,) the next line that matches "Configured Voltage", print those lines (p)

                        4. quit ed: q


                        Because ed auto-prints the matching line when you search, I used sed here to delete those two lines.






                        share|improve this answer


























                          4












                          4








                          4







                          You could use ed ... and sed, man!



                          You have to want to use ed for this one, though, as ed wants to operate on a file, not as part of a pipeline.




                          1. command > dimm-output

                          2. wanted=P1-DIMMD1

                          3. ed -s dimm-output <<< $'/Location Tag: '"$wanted"$'n?^ID.*SIZE.*TYPEn.,/Configured Voltage/pnqn' | sed 1,2d


                          The ed command-string breaks down to four n-separated commands:




                          1. search forwards, using /, for the text "Location Tag: " followed by the value of the $wanted variable

                          2. search backwards, using ?, for the pattern: (start-of-line), "ID", anything, "SIZE", anything, "TYPE"

                          3. from that line (.), through (,) the next line that matches "Configured Voltage", print those lines (p)

                          4. quit ed: q


                          Because ed auto-prints the matching line when you search, I used sed here to delete those two lines.






                          share|improve this answer













                          You could use ed ... and sed, man!



                          You have to want to use ed for this one, though, as ed wants to operate on a file, not as part of a pipeline.




                          1. command > dimm-output

                          2. wanted=P1-DIMMD1

                          3. ed -s dimm-output <<< $'/Location Tag: '"$wanted"$'n?^ID.*SIZE.*TYPEn.,/Configured Voltage/pnqn' | sed 1,2d


                          The ed command-string breaks down to four n-separated commands:




                          1. search forwards, using /, for the text "Location Tag: " followed by the value of the $wanted variable

                          2. search backwards, using ?, for the pattern: (start-of-line), "ID", anything, "SIZE", anything, "TYPE"

                          3. from that line (.), through (,) the next line that matches "Configured Voltage", print those lines (p)

                          4. quit ed: q


                          Because ed auto-prints the matching line when you search, I used sed here to delete those two lines.







                          share|improve this answer












                          share|improve this answer



                          share|improve this answer










                          answered 14 hours ago









                          Jeff SchallerJeff Schaller

                          39.5k1054126




                          39.5k1054126























                              2














                              Inspired by @Stephen Kitts great answer, I wrote a little more general script to perform block matching when having a specified start and end pattern.



                              #!/bin/sh

                              [ -z "$4" ] && file="-" || file="$4"

                              awk
                              -v BLOCKSTART_PATTERN="$1"
                              -v BLOCKEND_PATTERN="$2"
                              -v BLOCKMATCH_PATTERN="$3"
                              '
                              $0 ~ BLOCKSTART_PATTERN { block = $0; output = 0; next }
                              { block = block "n" $0 }
                              $0 ~ BLOCKMATCH_PATTERN { output = 1 }
                              $0 ~ BLOCKEND_PATTERN && output { print block; output = 0 }
                              ' "$file"


                              Usage: match_block START END MATCH [FILE].

                              If file is omitted, stdin will be used.



                              In your case:



                              command | ./match_block '^ID' 'Configured Voltage' 'Location Tag: P1-DIMMD1'


                              or



                              ./match_block '^ID' 'Configured Voltage' 'Location Tag: P1-DIMMD1' file





                              share|improve this answer
























                              • You could even write this directly as an AWK script, instead of a shell script which calls AWK.

                                – Stephen Kitt
                                14 hours ago
















                              2














                              Inspired by @Stephen Kitts great answer, I wrote a little more general script to perform block matching when having a specified start and end pattern.



                              #!/bin/sh

                              [ -z "$4" ] && file="-" || file="$4"

                              awk
                              -v BLOCKSTART_PATTERN="$1"
                              -v BLOCKEND_PATTERN="$2"
                              -v BLOCKMATCH_PATTERN="$3"
                              '
                              $0 ~ BLOCKSTART_PATTERN { block = $0; output = 0; next }
                              { block = block "n" $0 }
                              $0 ~ BLOCKMATCH_PATTERN { output = 1 }
                              $0 ~ BLOCKEND_PATTERN && output { print block; output = 0 }
                              ' "$file"


                              Usage: match_block START END MATCH [FILE].

                              If file is omitted, stdin will be used.



                              In your case:



                              command | ./match_block '^ID' 'Configured Voltage' 'Location Tag: P1-DIMMD1'


                              or



                              ./match_block '^ID' 'Configured Voltage' 'Location Tag: P1-DIMMD1' file





                              share|improve this answer
























                              • You could even write this directly as an AWK script, instead of a shell script which calls AWK.

                                – Stephen Kitt
                                14 hours ago














                              2












                              2








                              2







                              Inspired by @Stephen Kitts great answer, I wrote a little more general script to perform block matching when having a specified start and end pattern.



                              #!/bin/sh

                              [ -z "$4" ] && file="-" || file="$4"

                              awk
                              -v BLOCKSTART_PATTERN="$1"
                              -v BLOCKEND_PATTERN="$2"
                              -v BLOCKMATCH_PATTERN="$3"
                              '
                              $0 ~ BLOCKSTART_PATTERN { block = $0; output = 0; next }
                              { block = block "n" $0 }
                              $0 ~ BLOCKMATCH_PATTERN { output = 1 }
                              $0 ~ BLOCKEND_PATTERN && output { print block; output = 0 }
                              ' "$file"


                              Usage: match_block START END MATCH [FILE].

                              If file is omitted, stdin will be used.



                              In your case:



                              command | ./match_block '^ID' 'Configured Voltage' 'Location Tag: P1-DIMMD1'


                              or



                              ./match_block '^ID' 'Configured Voltage' 'Location Tag: P1-DIMMD1' file





                              share|improve this answer













                              Inspired by @Stephen Kitts great answer, I wrote a little more general script to perform block matching when having a specified start and end pattern.



                              #!/bin/sh

                              [ -z "$4" ] && file="-" || file="$4"

                              awk
                              -v BLOCKSTART_PATTERN="$1"
                              -v BLOCKEND_PATTERN="$2"
                              -v BLOCKMATCH_PATTERN="$3"
                              '
                              $0 ~ BLOCKSTART_PATTERN { block = $0; output = 0; next }
                              { block = block "n" $0 }
                              $0 ~ BLOCKMATCH_PATTERN { output = 1 }
                              $0 ~ BLOCKEND_PATTERN && output { print block; output = 0 }
                              ' "$file"


                              Usage: match_block START END MATCH [FILE].

                              If file is omitted, stdin will be used.



                              In your case:



                              command | ./match_block '^ID' 'Configured Voltage' 'Location Tag: P1-DIMMD1'


                              or



                              ./match_block '^ID' 'Configured Voltage' 'Location Tag: P1-DIMMD1' file






                              share|improve this answer












                              share|improve this answer



                              share|improve this answer










                              answered 14 hours ago









                              RoVoRoVo

                              2,773216




                              2,773216













                              • You could even write this directly as an AWK script, instead of a shell script which calls AWK.

                                – Stephen Kitt
                                14 hours ago



















                              • You could even write this directly as an AWK script, instead of a shell script which calls AWK.

                                – Stephen Kitt
                                14 hours ago

















                              You could even write this directly as an AWK script, instead of a shell script which calls AWK.

                              – Stephen Kitt
                              14 hours ago





                              You could even write this directly as an AWK script, instead of a shell script which calls AWK.

                              – Stephen Kitt
                              14 hours 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%2f495094%2fextract-multiple-lines-if-match%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

                              Loup dans la culture

                              How to solve the problem of ntp “Unable to contact time server” from KDE?

                              ASUS Zenbook UX433/UX333 — Configure Touchpad-embedded numpad on Linux