How to print lines between same pattern with muliple occurrence?

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
3
down vote

favorite












Need to extract the lines between the same pattern with specified occurrence of the search Pattern



like if I want to get the lines between 1st & 2nd occurrence or lines between 3rd and 4th occurrence of search pattern. Where no of lines may very between the pattern, if no lines between pattern then output should be blank



Example: -



Line 1
Line 2
Line 3
Pattern
Line 5
Line 6
Line 7
Pattern
Line 8
Line 9
Pattern
Line 11
Line 12
Pattern
Line 13
Pattern
Pattern


Expected Output
Lines Between 1st and 2nd Occurrence



Line 5
Line 6
Line 7


Lines between 3rd and 4th occurrence



Line 11
Line 12









share|improve this question























  • Please help with Single line command if possible
    – Vasanta Koli
    May 18 '17 at 6:45










  • unix.stackexchange.com/search?q=awk+lines+between+pattern
    – Sparhawk
    May 18 '17 at 6:52










  • This does not include selection of pattern in between.
    – Vasanta Koli
    May 18 '17 at 7:01










  • Third hit. Although I'm not sure what your expected output is exactly. You have two code blocks as output. Do they represent separate files?
    – Sparhawk
    May 18 '17 at 7:02










  • Yes Output would be in different files and the input would be a single file.
    – Vasanta Koli
    May 18 '17 at 7:03














up vote
3
down vote

favorite












Need to extract the lines between the same pattern with specified occurrence of the search Pattern



like if I want to get the lines between 1st & 2nd occurrence or lines between 3rd and 4th occurrence of search pattern. Where no of lines may very between the pattern, if no lines between pattern then output should be blank



Example: -



Line 1
Line 2
Line 3
Pattern
Line 5
Line 6
Line 7
Pattern
Line 8
Line 9
Pattern
Line 11
Line 12
Pattern
Line 13
Pattern
Pattern


Expected Output
Lines Between 1st and 2nd Occurrence



Line 5
Line 6
Line 7


Lines between 3rd and 4th occurrence



Line 11
Line 12









share|improve this question























  • Please help with Single line command if possible
    – Vasanta Koli
    May 18 '17 at 6:45










  • unix.stackexchange.com/search?q=awk+lines+between+pattern
    – Sparhawk
    May 18 '17 at 6:52










  • This does not include selection of pattern in between.
    – Vasanta Koli
    May 18 '17 at 7:01










  • Third hit. Although I'm not sure what your expected output is exactly. You have two code blocks as output. Do they represent separate files?
    – Sparhawk
    May 18 '17 at 7:02










  • Yes Output would be in different files and the input would be a single file.
    – Vasanta Koli
    May 18 '17 at 7:03












up vote
3
down vote

favorite









up vote
3
down vote

favorite











Need to extract the lines between the same pattern with specified occurrence of the search Pattern



like if I want to get the lines between 1st & 2nd occurrence or lines between 3rd and 4th occurrence of search pattern. Where no of lines may very between the pattern, if no lines between pattern then output should be blank



Example: -



Line 1
Line 2
Line 3
Pattern
Line 5
Line 6
Line 7
Pattern
Line 8
Line 9
Pattern
Line 11
Line 12
Pattern
Line 13
Pattern
Pattern


Expected Output
Lines Between 1st and 2nd Occurrence



Line 5
Line 6
Line 7


Lines between 3rd and 4th occurrence



Line 11
Line 12









share|improve this question















Need to extract the lines between the same pattern with specified occurrence of the search Pattern



like if I want to get the lines between 1st & 2nd occurrence or lines between 3rd and 4th occurrence of search pattern. Where no of lines may very between the pattern, if no lines between pattern then output should be blank



Example: -



Line 1
Line 2
Line 3
Pattern
Line 5
Line 6
Line 7
Pattern
Line 8
Line 9
Pattern
Line 11
Line 12
Pattern
Line 13
Pattern
Pattern


Expected Output
Lines Between 1st and 2nd Occurrence



Line 5
Line 6
Line 7


Lines between 3rd and 4th occurrence



Line 11
Line 12






awk sed






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 17 at 2:22









Rui F Ribeiro

38.2k1475123




38.2k1475123










asked May 18 '17 at 6:40









Vasanta Koli

1186




1186











  • Please help with Single line command if possible
    – Vasanta Koli
    May 18 '17 at 6:45










  • unix.stackexchange.com/search?q=awk+lines+between+pattern
    – Sparhawk
    May 18 '17 at 6:52










  • This does not include selection of pattern in between.
    – Vasanta Koli
    May 18 '17 at 7:01










  • Third hit. Although I'm not sure what your expected output is exactly. You have two code blocks as output. Do they represent separate files?
    – Sparhawk
    May 18 '17 at 7:02










  • Yes Output would be in different files and the input would be a single file.
    – Vasanta Koli
    May 18 '17 at 7:03
















  • Please help with Single line command if possible
    – Vasanta Koli
    May 18 '17 at 6:45










  • unix.stackexchange.com/search?q=awk+lines+between+pattern
    – Sparhawk
    May 18 '17 at 6:52










  • This does not include selection of pattern in between.
    – Vasanta Koli
    May 18 '17 at 7:01










  • Third hit. Although I'm not sure what your expected output is exactly. You have two code blocks as output. Do they represent separate files?
    – Sparhawk
    May 18 '17 at 7:02










  • Yes Output would be in different files and the input would be a single file.
    – Vasanta Koli
    May 18 '17 at 7:03















Please help with Single line command if possible
– Vasanta Koli
May 18 '17 at 6:45




Please help with Single line command if possible
– Vasanta Koli
May 18 '17 at 6:45












unix.stackexchange.com/search?q=awk+lines+between+pattern
– Sparhawk
May 18 '17 at 6:52




unix.stackexchange.com/search?q=awk+lines+between+pattern
– Sparhawk
May 18 '17 at 6:52












This does not include selection of pattern in between.
– Vasanta Koli
May 18 '17 at 7:01




This does not include selection of pattern in between.
– Vasanta Koli
May 18 '17 at 7:01












Third hit. Although I'm not sure what your expected output is exactly. You have two code blocks as output. Do they represent separate files?
– Sparhawk
May 18 '17 at 7:02




Third hit. Although I'm not sure what your expected output is exactly. You have two code blocks as output. Do they represent separate files?
– Sparhawk
May 18 '17 at 7:02












Yes Output would be in different files and the input would be a single file.
– Vasanta Koli
May 18 '17 at 7:03




Yes Output would be in different files and the input would be a single file.
– Vasanta Koli
May 18 '17 at 7:03










4 Answers
4






active

oldest

votes

















up vote
2
down vote



accepted










Based on this answer,



awk '/Pattern/n+=1; n % 2 == 1 && ! /Pattern/ print > "output"((n-1)/2)' input_file 


Explanation




  • /Pattern/n+=1: when you match Pattern, increment n by 1.


  • n % 2 == 1 && ! /Pattern/: only do the following then n is odd, i.e. after every alternate pattern. Also, ignore the lines with Pattern on them.


  • print > "output"((n+1)/2)': if the above holds, then print that line into a file named outputx, where x is ((n+1)/2), i.e. output1, output2, output3





share|improve this answer




















  • Sure let me try this one and update you on the same
    – Vasanta Koli
    May 18 '17 at 7:17










  • This is working best for me Thanks for your help, I'll need to just pickup the files with the numbers, Above creates files with output0, output1 etc. in case the contents between pattern has no line, no output file is skipped where I can get numbers perfectly to work on, by taking exact number of output file
    – Vasanta Koli
    May 18 '17 at 7:23










  • No worries. If this answers your question (I'm not 100% sure if it does), please click the tick mark on the left.
    – Sparhawk
    May 18 '17 at 7:26










  • Already Done :P
    – Vasanta Koli
    May 18 '17 at 7:27










  • I think that was the upvote arrow, not the tick? :p
    – Sparhawk
    May 18 '17 at 7:27

















up vote
1
down vote













Alternative AWK approach



 $ awk -v start=3 '/Pattern/n++;next;n==start;n==start+1exit' input.txt 
Line 11
Line 12

$ awk -v start=2 '/Pattern/n++;next;n==start;n==start+1exit' input.txt
Line 8
Line 9


Explanation



The way this works is fairly straightforward:



  • using -v flag we define a variable which we increment if we find the matching pattern and go to next line(that's the /Pattern/n++;next part of the code)

  • in awk if condition is true, that's automatically a signal for printing stuff, hence n==start can be viewed same was as n==startprint.

  • final codeblock where we look if we got to the next pattern is n==start+1exit. Say we wanted to print lines between 4th and 5th pattern occurrence. This will mean that whenn==4+1` the code exits

If we were doing code-golf, we could make this even shorter by just changing start variable to something like -v s=1, which shortens the code like so:



awk -v s=3 '/Pattern/n++;next;n==s;n==s+1exit'


Assumptions:



  • GNU awk

  • we're reading between consecutive patterns, i.e. between match n and n+1

Generalizing the approach



What if we wanted to print lines between pattern 2 to pattern 4 ? Using a few of tricks used in the previous example, we can do that as well like so:



$ awk -v start=2 -v finish=4 '/Pattern/n++;next;n==finishexit;n>=start' input.txt 
Line 8
Line 9
Line 11
Line 12


Notice that here we define another variable,finish, to know where to stop. This way n==finish will stop printing the lines. Notice also that n==finishexit comes before n>=start, which allows us to avoid redundant printing of the same line where we're supposed to exit.






share|improve this answer





























    up vote
    0
    down vote













    With sed:



    sed -n '/Pattern/!d;:a
    n;//! w file1.txt
    ba
    ;:b
    n;//! bb
    :c
    n;//q;w file2.txt
    bc
    ' file


    WIth POSIX sed You have to do 3 loops like this for the both matches and the in-between, as you can't generate filenames from within the script.






    share|improve this answer



























      up vote
      0
      down vote













      start=3; # these can only be positive integers
      stop=4; # stop > start

      perl -lne "// or print if /Pattern/ && ++$a == $start ... // && ++$a == $stop" data.in


      Perl solution uses the range operator ... where it's two operands act like flip-flops: => so long as the first operand is false, ... returns false. As soon as the first operand goes true, then the ... returns true. It will only go false when the second operand becomes true. The subtleyty arises due to the feature that the operand1 is not evaluated once it becomes true and operand2 is not evaluated while operand1 is false.



      sed -nE "
      /Pattern/!d
      x
      s/$/./
      /^[.]$start$/!x;d;
      x

      n

      :loop
      p;n
      /Pattern/
      x
      s/$/./
      /^.$stop$/q
      x

      bloop
      " data.in


      the sed solution uses the hold space for keeping a count of the number of times the pattern is seen. We keep rejectting lines so long as $start number of patterns not seen. As soon as the $start-th pattern arrives, we go into a loop which keeps reading the next line, printing it and all the while measuring whether $stop-th pattern is seen. Once seen, we quickly quit.






      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%2f365792%2fhow-to-print-lines-between-same-pattern-with-muliple-occurrence%23new-answer', 'question_page');

        );

        Post as a guest















        Required, but never shown

























        4 Answers
        4






        active

        oldest

        votes








        4 Answers
        4






        active

        oldest

        votes









        active

        oldest

        votes






        active

        oldest

        votes








        up vote
        2
        down vote



        accepted










        Based on this answer,



        awk '/Pattern/n+=1; n % 2 == 1 && ! /Pattern/ print > "output"((n-1)/2)' input_file 


        Explanation




        • /Pattern/n+=1: when you match Pattern, increment n by 1.


        • n % 2 == 1 && ! /Pattern/: only do the following then n is odd, i.e. after every alternate pattern. Also, ignore the lines with Pattern on them.


        • print > "output"((n+1)/2)': if the above holds, then print that line into a file named outputx, where x is ((n+1)/2), i.e. output1, output2, output3





        share|improve this answer




















        • Sure let me try this one and update you on the same
          – Vasanta Koli
          May 18 '17 at 7:17










        • This is working best for me Thanks for your help, I'll need to just pickup the files with the numbers, Above creates files with output0, output1 etc. in case the contents between pattern has no line, no output file is skipped where I can get numbers perfectly to work on, by taking exact number of output file
          – Vasanta Koli
          May 18 '17 at 7:23










        • No worries. If this answers your question (I'm not 100% sure if it does), please click the tick mark on the left.
          – Sparhawk
          May 18 '17 at 7:26










        • Already Done :P
          – Vasanta Koli
          May 18 '17 at 7:27










        • I think that was the upvote arrow, not the tick? :p
          – Sparhawk
          May 18 '17 at 7:27














        up vote
        2
        down vote



        accepted










        Based on this answer,



        awk '/Pattern/n+=1; n % 2 == 1 && ! /Pattern/ print > "output"((n-1)/2)' input_file 


        Explanation




        • /Pattern/n+=1: when you match Pattern, increment n by 1.


        • n % 2 == 1 && ! /Pattern/: only do the following then n is odd, i.e. after every alternate pattern. Also, ignore the lines with Pattern on them.


        • print > "output"((n+1)/2)': if the above holds, then print that line into a file named outputx, where x is ((n+1)/2), i.e. output1, output2, output3





        share|improve this answer




















        • Sure let me try this one and update you on the same
          – Vasanta Koli
          May 18 '17 at 7:17










        • This is working best for me Thanks for your help, I'll need to just pickup the files with the numbers, Above creates files with output0, output1 etc. in case the contents between pattern has no line, no output file is skipped where I can get numbers perfectly to work on, by taking exact number of output file
          – Vasanta Koli
          May 18 '17 at 7:23










        • No worries. If this answers your question (I'm not 100% sure if it does), please click the tick mark on the left.
          – Sparhawk
          May 18 '17 at 7:26










        • Already Done :P
          – Vasanta Koli
          May 18 '17 at 7:27










        • I think that was the upvote arrow, not the tick? :p
          – Sparhawk
          May 18 '17 at 7:27












        up vote
        2
        down vote



        accepted







        up vote
        2
        down vote



        accepted






        Based on this answer,



        awk '/Pattern/n+=1; n % 2 == 1 && ! /Pattern/ print > "output"((n-1)/2)' input_file 


        Explanation




        • /Pattern/n+=1: when you match Pattern, increment n by 1.


        • n % 2 == 1 && ! /Pattern/: only do the following then n is odd, i.e. after every alternate pattern. Also, ignore the lines with Pattern on them.


        • print > "output"((n+1)/2)': if the above holds, then print that line into a file named outputx, where x is ((n+1)/2), i.e. output1, output2, output3





        share|improve this answer












        Based on this answer,



        awk '/Pattern/n+=1; n % 2 == 1 && ! /Pattern/ print > "output"((n-1)/2)' input_file 


        Explanation




        • /Pattern/n+=1: when you match Pattern, increment n by 1.


        • n % 2 == 1 && ! /Pattern/: only do the following then n is odd, i.e. after every alternate pattern. Also, ignore the lines with Pattern on them.


        • print > "output"((n+1)/2)': if the above holds, then print that line into a file named outputx, where x is ((n+1)/2), i.e. output1, output2, output3






        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered May 18 '17 at 7:10









        Sparhawk

        8,82763789




        8,82763789











        • Sure let me try this one and update you on the same
          – Vasanta Koli
          May 18 '17 at 7:17










        • This is working best for me Thanks for your help, I'll need to just pickup the files with the numbers, Above creates files with output0, output1 etc. in case the contents between pattern has no line, no output file is skipped where I can get numbers perfectly to work on, by taking exact number of output file
          – Vasanta Koli
          May 18 '17 at 7:23










        • No worries. If this answers your question (I'm not 100% sure if it does), please click the tick mark on the left.
          – Sparhawk
          May 18 '17 at 7:26










        • Already Done :P
          – Vasanta Koli
          May 18 '17 at 7:27










        • I think that was the upvote arrow, not the tick? :p
          – Sparhawk
          May 18 '17 at 7:27
















        • Sure let me try this one and update you on the same
          – Vasanta Koli
          May 18 '17 at 7:17










        • This is working best for me Thanks for your help, I'll need to just pickup the files with the numbers, Above creates files with output0, output1 etc. in case the contents between pattern has no line, no output file is skipped where I can get numbers perfectly to work on, by taking exact number of output file
          – Vasanta Koli
          May 18 '17 at 7:23










        • No worries. If this answers your question (I'm not 100% sure if it does), please click the tick mark on the left.
          – Sparhawk
          May 18 '17 at 7:26










        • Already Done :P
          – Vasanta Koli
          May 18 '17 at 7:27










        • I think that was the upvote arrow, not the tick? :p
          – Sparhawk
          May 18 '17 at 7:27















        Sure let me try this one and update you on the same
        – Vasanta Koli
        May 18 '17 at 7:17




        Sure let me try this one and update you on the same
        – Vasanta Koli
        May 18 '17 at 7:17












        This is working best for me Thanks for your help, I'll need to just pickup the files with the numbers, Above creates files with output0, output1 etc. in case the contents between pattern has no line, no output file is skipped where I can get numbers perfectly to work on, by taking exact number of output file
        – Vasanta Koli
        May 18 '17 at 7:23




        This is working best for me Thanks for your help, I'll need to just pickup the files with the numbers, Above creates files with output0, output1 etc. in case the contents between pattern has no line, no output file is skipped where I can get numbers perfectly to work on, by taking exact number of output file
        – Vasanta Koli
        May 18 '17 at 7:23












        No worries. If this answers your question (I'm not 100% sure if it does), please click the tick mark on the left.
        – Sparhawk
        May 18 '17 at 7:26




        No worries. If this answers your question (I'm not 100% sure if it does), please click the tick mark on the left.
        – Sparhawk
        May 18 '17 at 7:26












        Already Done :P
        – Vasanta Koli
        May 18 '17 at 7:27




        Already Done :P
        – Vasanta Koli
        May 18 '17 at 7:27












        I think that was the upvote arrow, not the tick? :p
        – Sparhawk
        May 18 '17 at 7:27




        I think that was the upvote arrow, not the tick? :p
        – Sparhawk
        May 18 '17 at 7:27












        up vote
        1
        down vote













        Alternative AWK approach



         $ awk -v start=3 '/Pattern/n++;next;n==start;n==start+1exit' input.txt 
        Line 11
        Line 12

        $ awk -v start=2 '/Pattern/n++;next;n==start;n==start+1exit' input.txt
        Line 8
        Line 9


        Explanation



        The way this works is fairly straightforward:



        • using -v flag we define a variable which we increment if we find the matching pattern and go to next line(that's the /Pattern/n++;next part of the code)

        • in awk if condition is true, that's automatically a signal for printing stuff, hence n==start can be viewed same was as n==startprint.

        • final codeblock where we look if we got to the next pattern is n==start+1exit. Say we wanted to print lines between 4th and 5th pattern occurrence. This will mean that whenn==4+1` the code exits

        If we were doing code-golf, we could make this even shorter by just changing start variable to something like -v s=1, which shortens the code like so:



        awk -v s=3 '/Pattern/n++;next;n==s;n==s+1exit'


        Assumptions:



        • GNU awk

        • we're reading between consecutive patterns, i.e. between match n and n+1

        Generalizing the approach



        What if we wanted to print lines between pattern 2 to pattern 4 ? Using a few of tricks used in the previous example, we can do that as well like so:



        $ awk -v start=2 -v finish=4 '/Pattern/n++;next;n==finishexit;n>=start' input.txt 
        Line 8
        Line 9
        Line 11
        Line 12


        Notice that here we define another variable,finish, to know where to stop. This way n==finish will stop printing the lines. Notice also that n==finishexit comes before n>=start, which allows us to avoid redundant printing of the same line where we're supposed to exit.






        share|improve this answer


























          up vote
          1
          down vote













          Alternative AWK approach



           $ awk -v start=3 '/Pattern/n++;next;n==start;n==start+1exit' input.txt 
          Line 11
          Line 12

          $ awk -v start=2 '/Pattern/n++;next;n==start;n==start+1exit' input.txt
          Line 8
          Line 9


          Explanation



          The way this works is fairly straightforward:



          • using -v flag we define a variable which we increment if we find the matching pattern and go to next line(that's the /Pattern/n++;next part of the code)

          • in awk if condition is true, that's automatically a signal for printing stuff, hence n==start can be viewed same was as n==startprint.

          • final codeblock where we look if we got to the next pattern is n==start+1exit. Say we wanted to print lines between 4th and 5th pattern occurrence. This will mean that whenn==4+1` the code exits

          If we were doing code-golf, we could make this even shorter by just changing start variable to something like -v s=1, which shortens the code like so:



          awk -v s=3 '/Pattern/n++;next;n==s;n==s+1exit'


          Assumptions:



          • GNU awk

          • we're reading between consecutive patterns, i.e. between match n and n+1

          Generalizing the approach



          What if we wanted to print lines between pattern 2 to pattern 4 ? Using a few of tricks used in the previous example, we can do that as well like so:



          $ awk -v start=2 -v finish=4 '/Pattern/n++;next;n==finishexit;n>=start' input.txt 
          Line 8
          Line 9
          Line 11
          Line 12


          Notice that here we define another variable,finish, to know where to stop. This way n==finish will stop printing the lines. Notice also that n==finishexit comes before n>=start, which allows us to avoid redundant printing of the same line where we're supposed to exit.






          share|improve this answer
























            up vote
            1
            down vote










            up vote
            1
            down vote









            Alternative AWK approach



             $ awk -v start=3 '/Pattern/n++;next;n==start;n==start+1exit' input.txt 
            Line 11
            Line 12

            $ awk -v start=2 '/Pattern/n++;next;n==start;n==start+1exit' input.txt
            Line 8
            Line 9


            Explanation



            The way this works is fairly straightforward:



            • using -v flag we define a variable which we increment if we find the matching pattern and go to next line(that's the /Pattern/n++;next part of the code)

            • in awk if condition is true, that's automatically a signal for printing stuff, hence n==start can be viewed same was as n==startprint.

            • final codeblock where we look if we got to the next pattern is n==start+1exit. Say we wanted to print lines between 4th and 5th pattern occurrence. This will mean that whenn==4+1` the code exits

            If we were doing code-golf, we could make this even shorter by just changing start variable to something like -v s=1, which shortens the code like so:



            awk -v s=3 '/Pattern/n++;next;n==s;n==s+1exit'


            Assumptions:



            • GNU awk

            • we're reading between consecutive patterns, i.e. between match n and n+1

            Generalizing the approach



            What if we wanted to print lines between pattern 2 to pattern 4 ? Using a few of tricks used in the previous example, we can do that as well like so:



            $ awk -v start=2 -v finish=4 '/Pattern/n++;next;n==finishexit;n>=start' input.txt 
            Line 8
            Line 9
            Line 11
            Line 12


            Notice that here we define another variable,finish, to know where to stop. This way n==finish will stop printing the lines. Notice also that n==finishexit comes before n>=start, which allows us to avoid redundant printing of the same line where we're supposed to exit.






            share|improve this answer














            Alternative AWK approach



             $ awk -v start=3 '/Pattern/n++;next;n==start;n==start+1exit' input.txt 
            Line 11
            Line 12

            $ awk -v start=2 '/Pattern/n++;next;n==start;n==start+1exit' input.txt
            Line 8
            Line 9


            Explanation



            The way this works is fairly straightforward:



            • using -v flag we define a variable which we increment if we find the matching pattern and go to next line(that's the /Pattern/n++;next part of the code)

            • in awk if condition is true, that's automatically a signal for printing stuff, hence n==start can be viewed same was as n==startprint.

            • final codeblock where we look if we got to the next pattern is n==start+1exit. Say we wanted to print lines between 4th and 5th pattern occurrence. This will mean that whenn==4+1` the code exits

            If we were doing code-golf, we could make this even shorter by just changing start variable to something like -v s=1, which shortens the code like so:



            awk -v s=3 '/Pattern/n++;next;n==s;n==s+1exit'


            Assumptions:



            • GNU awk

            • we're reading between consecutive patterns, i.e. between match n and n+1

            Generalizing the approach



            What if we wanted to print lines between pattern 2 to pattern 4 ? Using a few of tricks used in the previous example, we can do that as well like so:



            $ awk -v start=2 -v finish=4 '/Pattern/n++;next;n==finishexit;n>=start' input.txt 
            Line 8
            Line 9
            Line 11
            Line 12


            Notice that here we define another variable,finish, to know where to stop. This way n==finish will stop printing the lines. Notice also that n==finishexit comes before n>=start, which allows us to avoid redundant printing of the same line where we're supposed to exit.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited May 18 '17 at 7:51

























            answered May 18 '17 at 7:35









            Sergiy Kolodyazhnyy

            8,08712051




            8,08712051




















                up vote
                0
                down vote













                With sed:



                sed -n '/Pattern/!d;:a
                n;//! w file1.txt
                ba
                ;:b
                n;//! bb
                :c
                n;//q;w file2.txt
                bc
                ' file


                WIth POSIX sed You have to do 3 loops like this for the both matches and the in-between, as you can't generate filenames from within the script.






                share|improve this answer
























                  up vote
                  0
                  down vote













                  With sed:



                  sed -n '/Pattern/!d;:a
                  n;//! w file1.txt
                  ba
                  ;:b
                  n;//! bb
                  :c
                  n;//q;w file2.txt
                  bc
                  ' file


                  WIth POSIX sed You have to do 3 loops like this for the both matches and the in-between, as you can't generate filenames from within the script.






                  share|improve this answer






















                    up vote
                    0
                    down vote










                    up vote
                    0
                    down vote









                    With sed:



                    sed -n '/Pattern/!d;:a
                    n;//! w file1.txt
                    ba
                    ;:b
                    n;//! bb
                    :c
                    n;//q;w file2.txt
                    bc
                    ' file


                    WIth POSIX sed You have to do 3 loops like this for the both matches and the in-between, as you can't generate filenames from within the script.






                    share|improve this answer












                    With sed:



                    sed -n '/Pattern/!d;:a
                    n;//! w file1.txt
                    ba
                    ;:b
                    n;//! bb
                    :c
                    n;//q;w file2.txt
                    bc
                    ' file


                    WIth POSIX sed You have to do 3 loops like this for the both matches and the in-between, as you can't generate filenames from within the script.







                    share|improve this answer












                    share|improve this answer



                    share|improve this answer










                    answered May 18 '17 at 7:26









                    Philippos

                    5,98211547




                    5,98211547




















                        up vote
                        0
                        down vote













                        start=3; # these can only be positive integers
                        stop=4; # stop > start

                        perl -lne "// or print if /Pattern/ && ++$a == $start ... // && ++$a == $stop" data.in


                        Perl solution uses the range operator ... where it's two operands act like flip-flops: => so long as the first operand is false, ... returns false. As soon as the first operand goes true, then the ... returns true. It will only go false when the second operand becomes true. The subtleyty arises due to the feature that the operand1 is not evaluated once it becomes true and operand2 is not evaluated while operand1 is false.



                        sed -nE "
                        /Pattern/!d
                        x
                        s/$/./
                        /^[.]$start$/!x;d;
                        x

                        n

                        :loop
                        p;n
                        /Pattern/
                        x
                        s/$/./
                        /^.$stop$/q
                        x

                        bloop
                        " data.in


                        the sed solution uses the hold space for keeping a count of the number of times the pattern is seen. We keep rejectting lines so long as $start number of patterns not seen. As soon as the $start-th pattern arrives, we go into a loop which keeps reading the next line, printing it and all the while measuring whether $stop-th pattern is seen. Once seen, we quickly quit.






                        share|improve this answer
























                          up vote
                          0
                          down vote













                          start=3; # these can only be positive integers
                          stop=4; # stop > start

                          perl -lne "// or print if /Pattern/ && ++$a == $start ... // && ++$a == $stop" data.in


                          Perl solution uses the range operator ... where it's two operands act like flip-flops: => so long as the first operand is false, ... returns false. As soon as the first operand goes true, then the ... returns true. It will only go false when the second operand becomes true. The subtleyty arises due to the feature that the operand1 is not evaluated once it becomes true and operand2 is not evaluated while operand1 is false.



                          sed -nE "
                          /Pattern/!d
                          x
                          s/$/./
                          /^[.]$start$/!x;d;
                          x

                          n

                          :loop
                          p;n
                          /Pattern/
                          x
                          s/$/./
                          /^.$stop$/q
                          x

                          bloop
                          " data.in


                          the sed solution uses the hold space for keeping a count of the number of times the pattern is seen. We keep rejectting lines so long as $start number of patterns not seen. As soon as the $start-th pattern arrives, we go into a loop which keeps reading the next line, printing it and all the while measuring whether $stop-th pattern is seen. Once seen, we quickly quit.






                          share|improve this answer






















                            up vote
                            0
                            down vote










                            up vote
                            0
                            down vote









                            start=3; # these can only be positive integers
                            stop=4; # stop > start

                            perl -lne "// or print if /Pattern/ && ++$a == $start ... // && ++$a == $stop" data.in


                            Perl solution uses the range operator ... where it's two operands act like flip-flops: => so long as the first operand is false, ... returns false. As soon as the first operand goes true, then the ... returns true. It will only go false when the second operand becomes true. The subtleyty arises due to the feature that the operand1 is not evaluated once it becomes true and operand2 is not evaluated while operand1 is false.



                            sed -nE "
                            /Pattern/!d
                            x
                            s/$/./
                            /^[.]$start$/!x;d;
                            x

                            n

                            :loop
                            p;n
                            /Pattern/
                            x
                            s/$/./
                            /^.$stop$/q
                            x

                            bloop
                            " data.in


                            the sed solution uses the hold space for keeping a count of the number of times the pattern is seen. We keep rejectting lines so long as $start number of patterns not seen. As soon as the $start-th pattern arrives, we go into a loop which keeps reading the next line, printing it and all the while measuring whether $stop-th pattern is seen. Once seen, we quickly quit.






                            share|improve this answer












                            start=3; # these can only be positive integers
                            stop=4; # stop > start

                            perl -lne "// or print if /Pattern/ && ++$a == $start ... // && ++$a == $stop" data.in


                            Perl solution uses the range operator ... where it's two operands act like flip-flops: => so long as the first operand is false, ... returns false. As soon as the first operand goes true, then the ... returns true. It will only go false when the second operand becomes true. The subtleyty arises due to the feature that the operand1 is not evaluated once it becomes true and operand2 is not evaluated while operand1 is false.



                            sed -nE "
                            /Pattern/!d
                            x
                            s/$/./
                            /^[.]$start$/!x;d;
                            x

                            n

                            :loop
                            p;n
                            /Pattern/
                            x
                            s/$/./
                            /^.$stop$/q
                            x

                            bloop
                            " data.in


                            the sed solution uses the hold space for keeping a count of the number of times the pattern is seen. We keep rejectting lines so long as $start number of patterns not seen. As soon as the $start-th pattern arrives, we go into a loop which keeps reading the next line, printing it and all the while measuring whether $stop-th pattern is seen. Once seen, we quickly quit.







                            share|improve this answer












                            share|improve this answer



                            share|improve this answer










                            answered May 18 '17 at 10:30







                            user218374


































                                 

                                draft saved


                                draft discarded















































                                 


                                draft saved


                                draft discarded














                                StackExchange.ready(
                                function ()
                                StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f365792%2fhow-to-print-lines-between-same-pattern-with-muliple-occurrence%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

                                How to check contact read email or not when send email to Individual?

                                Displaying single band from multi-band raster using QGIS

                                How many registers does an x86_64 CPU actually have?