Delete newline characters between patterns

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











up vote
0
down vote

favorite












foo
I love
Stack Exchange
bar
Some junk
lines
foo
Welcome to the
world of
Bash
bar
foo
Elon Musk
rocks


Yes, there is no bar complementing foo at the end of the file



The required output is



I love Stack Exchange
Welcome to the world of Bash
Elon Musk rocks


So, remove all newline characters, between ^foo and ^bar or between ^foo and the end of file where there is no bar










share|improve this question



























    up vote
    0
    down vote

    favorite












    foo
    I love
    Stack Exchange
    bar
    Some junk
    lines
    foo
    Welcome to the
    world of
    Bash
    bar
    foo
    Elon Musk
    rocks


    Yes, there is no bar complementing foo at the end of the file



    The required output is



    I love Stack Exchange
    Welcome to the world of Bash
    Elon Musk rocks


    So, remove all newline characters, between ^foo and ^bar or between ^foo and the end of file where there is no bar










    share|improve this question

























      up vote
      0
      down vote

      favorite









      up vote
      0
      down vote

      favorite











      foo
      I love
      Stack Exchange
      bar
      Some junk
      lines
      foo
      Welcome to the
      world of
      Bash
      bar
      foo
      Elon Musk
      rocks


      Yes, there is no bar complementing foo at the end of the file



      The required output is



      I love Stack Exchange
      Welcome to the world of Bash
      Elon Musk rocks


      So, remove all newline characters, between ^foo and ^bar or between ^foo and the end of file where there is no bar










      share|improve this question















      foo
      I love
      Stack Exchange
      bar
      Some junk
      lines
      foo
      Welcome to the
      world of
      Bash
      bar
      foo
      Elon Musk
      rocks


      Yes, there is no bar complementing foo at the end of the file



      The required output is



      I love Stack Exchange
      Welcome to the world of Bash
      Elon Musk rocks


      So, remove all newline characters, between ^foo and ^bar or between ^foo and the end of file where there is no bar







      text-processing awk sed perl






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Sep 18 at 9:25









      αғsнιη

      16k92563




      16k92563










      asked Sep 17 at 0:17









      GypsyCosmonaut

      718628




      718628




















          3 Answers
          3






          active

          oldest

          votes

















          up vote
          2
          down vote



          accepted










          With awk:



          awk '
          $0 == "foo" if (sep) print ""; sep = ""; inside = 1; next
          $0 == "bar" inside = 0; next
          inside printf "%s", sep $0; sep = " "
          END if (sep) print ""'


          To match on lines with foo as the first word, replace $0 == "foo" with $1 == "foo"; to match on lines starting with foo, replace with /^foo/ (short for $0 ~ /^foo/).






          share|improve this answer





























            up vote
            2
            down vote













            Perl to the rescue!



            perl -ne '
            if ($e = /^foo$/ .. /^bar$/)
            if ($e =~ /E/) print "n"
            else
            chomp;
            print " " if $e > 2;
            print if $e > 1;

            ' -- input.txt



            • -n reads the input line by line


            • .. is the range operator, it returns the relative line number for each line in a block. The last line has E0 appended to it.





            share|improve this answer






















            • Why are >2 and >1 used here and what are they doing basically?
              – GypsyCosmonaut
              Sep 17 at 1:13










            • It's numerical comparison. $e > 2 excludes the first two lines of each block, $e > 1 excludes only the first (foo) one.
              – choroba
              Sep 17 at 1:30






            • 1




              Yes, you can move the $e > 1 one level up: perl -ne 'if ($e = /^foo$/ .. /^bar$/) if ($e =~ /E/) print "n" elsif ($e > 1) chomp; print " " if $e > 2; print; ' -- file
              – choroba
              Sep 17 at 1:49

















            up vote
            2
            down vote













            You could do this way also:



            a) This is POSIX-sed compliant code wherein we store the mid-range lines (!/foo/ and !/bar/) in the hold area.



            sed -e '
            /foo/,/bar/!d
            /foo/d
            /bar/!H;$!d;
            s/.*//;x;s/^n//;y/n/ /
            ' input-file.txt


            b) and with Perl as shown



            perl -lne '
            next unless /foo/ ... /bar/;
            push(@A, $_),next if !/foo/ && !/bar/ && !eof;
            push(@A, $_) if !/foo/ && !/bar/ && eof;
            print join " ", splice @A if /bar/ || !/foo/ && eof;
            ' input-file.txt


            Explanation:



            • skip non-interesting lines or lines that fall out of range. A range is defined as beginning with a line containing /foo/ and ending with /bar/, both occurring on separate lines.

            • Once we are in the range, then perform separate actions based on what line we are in.

            • For lines that are not /foo/, neither /bar/, and neither eof : store the line in the array @A. After storing, go back for reading the next record provided not eof.

            • Only for the end of range, i.e., /bar/ or eof, we take the action of printing what's in @A and also emptying it, in preparation for the next gathering cycle.





            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: false,
              showLowRepImageUploadWarning: true,
              reputationToPostImages: null,
              bindNavPrevention: true,
              postfix: "",
              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%2f469458%2fdelete-newline-characters-between-patterns%23new-answer', 'question_page');

              );

              Post as a guest






























              3 Answers
              3






              active

              oldest

              votes








              3 Answers
              3






              active

              oldest

              votes









              active

              oldest

              votes






              active

              oldest

              votes








              up vote
              2
              down vote



              accepted










              With awk:



              awk '
              $0 == "foo" if (sep) print ""; sep = ""; inside = 1; next
              $0 == "bar" inside = 0; next
              inside printf "%s", sep $0; sep = " "
              END if (sep) print ""'


              To match on lines with foo as the first word, replace $0 == "foo" with $1 == "foo"; to match on lines starting with foo, replace with /^foo/ (short for $0 ~ /^foo/).






              share|improve this answer


























                up vote
                2
                down vote



                accepted










                With awk:



                awk '
                $0 == "foo" if (sep) print ""; sep = ""; inside = 1; next
                $0 == "bar" inside = 0; next
                inside printf "%s", sep $0; sep = " "
                END if (sep) print ""'


                To match on lines with foo as the first word, replace $0 == "foo" with $1 == "foo"; to match on lines starting with foo, replace with /^foo/ (short for $0 ~ /^foo/).






                share|improve this answer
























                  up vote
                  2
                  down vote



                  accepted







                  up vote
                  2
                  down vote



                  accepted






                  With awk:



                  awk '
                  $0 == "foo" if (sep) print ""; sep = ""; inside = 1; next
                  $0 == "bar" inside = 0; next
                  inside printf "%s", sep $0; sep = " "
                  END if (sep) print ""'


                  To match on lines with foo as the first word, replace $0 == "foo" with $1 == "foo"; to match on lines starting with foo, replace with /^foo/ (short for $0 ~ /^foo/).






                  share|improve this answer














                  With awk:



                  awk '
                  $0 == "foo" if (sep) print ""; sep = ""; inside = 1; next
                  $0 == "bar" inside = 0; next
                  inside printf "%s", sep $0; sep = " "
                  END if (sep) print ""'


                  To match on lines with foo as the first word, replace $0 == "foo" with $1 == "foo"; to match on lines starting with foo, replace with /^foo/ (short for $0 ~ /^foo/).







                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited Sep 17 at 7:33

























                  answered Sep 17 at 7:00









                  Stéphane Chazelas

                  287k53528867




                  287k53528867






















                      up vote
                      2
                      down vote













                      Perl to the rescue!



                      perl -ne '
                      if ($e = /^foo$/ .. /^bar$/)
                      if ($e =~ /E/) print "n"
                      else
                      chomp;
                      print " " if $e > 2;
                      print if $e > 1;

                      ' -- input.txt



                      • -n reads the input line by line


                      • .. is the range operator, it returns the relative line number for each line in a block. The last line has E0 appended to it.





                      share|improve this answer






















                      • Why are >2 and >1 used here and what are they doing basically?
                        – GypsyCosmonaut
                        Sep 17 at 1:13










                      • It's numerical comparison. $e > 2 excludes the first two lines of each block, $e > 1 excludes only the first (foo) one.
                        – choroba
                        Sep 17 at 1:30






                      • 1




                        Yes, you can move the $e > 1 one level up: perl -ne 'if ($e = /^foo$/ .. /^bar$/) if ($e =~ /E/) print "n" elsif ($e > 1) chomp; print " " if $e > 2; print; ' -- file
                        – choroba
                        Sep 17 at 1:49














                      up vote
                      2
                      down vote













                      Perl to the rescue!



                      perl -ne '
                      if ($e = /^foo$/ .. /^bar$/)
                      if ($e =~ /E/) print "n"
                      else
                      chomp;
                      print " " if $e > 2;
                      print if $e > 1;

                      ' -- input.txt



                      • -n reads the input line by line


                      • .. is the range operator, it returns the relative line number for each line in a block. The last line has E0 appended to it.





                      share|improve this answer






















                      • Why are >2 and >1 used here and what are they doing basically?
                        – GypsyCosmonaut
                        Sep 17 at 1:13










                      • It's numerical comparison. $e > 2 excludes the first two lines of each block, $e > 1 excludes only the first (foo) one.
                        – choroba
                        Sep 17 at 1:30






                      • 1




                        Yes, you can move the $e > 1 one level up: perl -ne 'if ($e = /^foo$/ .. /^bar$/) if ($e =~ /E/) print "n" elsif ($e > 1) chomp; print " " if $e > 2; print; ' -- file
                        – choroba
                        Sep 17 at 1:49












                      up vote
                      2
                      down vote










                      up vote
                      2
                      down vote









                      Perl to the rescue!



                      perl -ne '
                      if ($e = /^foo$/ .. /^bar$/)
                      if ($e =~ /E/) print "n"
                      else
                      chomp;
                      print " " if $e > 2;
                      print if $e > 1;

                      ' -- input.txt



                      • -n reads the input line by line


                      • .. is the range operator, it returns the relative line number for each line in a block. The last line has E0 appended to it.





                      share|improve this answer














                      Perl to the rescue!



                      perl -ne '
                      if ($e = /^foo$/ .. /^bar$/)
                      if ($e =~ /E/) print "n"
                      else
                      chomp;
                      print " " if $e > 2;
                      print if $e > 1;

                      ' -- input.txt



                      • -n reads the input line by line


                      • .. is the range operator, it returns the relative line number for each line in a block. The last line has E0 appended to it.






                      share|improve this answer














                      share|improve this answer



                      share|improve this answer








                      edited Sep 17 at 1:47

























                      answered Sep 17 at 0:43









                      choroba

                      24.9k34168




                      24.9k34168











                      • Why are >2 and >1 used here and what are they doing basically?
                        – GypsyCosmonaut
                        Sep 17 at 1:13










                      • It's numerical comparison. $e > 2 excludes the first two lines of each block, $e > 1 excludes only the first (foo) one.
                        – choroba
                        Sep 17 at 1:30






                      • 1




                        Yes, you can move the $e > 1 one level up: perl -ne 'if ($e = /^foo$/ .. /^bar$/) if ($e =~ /E/) print "n" elsif ($e > 1) chomp; print " " if $e > 2; print; ' -- file
                        – choroba
                        Sep 17 at 1:49
















                      • Why are >2 and >1 used here and what are they doing basically?
                        – GypsyCosmonaut
                        Sep 17 at 1:13










                      • It's numerical comparison. $e > 2 excludes the first two lines of each block, $e > 1 excludes only the first (foo) one.
                        – choroba
                        Sep 17 at 1:30






                      • 1




                        Yes, you can move the $e > 1 one level up: perl -ne 'if ($e = /^foo$/ .. /^bar$/) if ($e =~ /E/) print "n" elsif ($e > 1) chomp; print " " if $e > 2; print; ' -- file
                        – choroba
                        Sep 17 at 1:49















                      Why are >2 and >1 used here and what are they doing basically?
                      – GypsyCosmonaut
                      Sep 17 at 1:13




                      Why are >2 and >1 used here and what are they doing basically?
                      – GypsyCosmonaut
                      Sep 17 at 1:13












                      It's numerical comparison. $e > 2 excludes the first two lines of each block, $e > 1 excludes only the first (foo) one.
                      – choroba
                      Sep 17 at 1:30




                      It's numerical comparison. $e > 2 excludes the first two lines of each block, $e > 1 excludes only the first (foo) one.
                      – choroba
                      Sep 17 at 1:30




                      1




                      1




                      Yes, you can move the $e > 1 one level up: perl -ne 'if ($e = /^foo$/ .. /^bar$/) if ($e =~ /E/) print "n" elsif ($e > 1) chomp; print " " if $e > 2; print; ' -- file
                      – choroba
                      Sep 17 at 1:49




                      Yes, you can move the $e > 1 one level up: perl -ne 'if ($e = /^foo$/ .. /^bar$/) if ($e =~ /E/) print "n" elsif ($e > 1) chomp; print " " if $e > 2; print; ' -- file
                      – choroba
                      Sep 17 at 1:49










                      up vote
                      2
                      down vote













                      You could do this way also:



                      a) This is POSIX-sed compliant code wherein we store the mid-range lines (!/foo/ and !/bar/) in the hold area.



                      sed -e '
                      /foo/,/bar/!d
                      /foo/d
                      /bar/!H;$!d;
                      s/.*//;x;s/^n//;y/n/ /
                      ' input-file.txt


                      b) and with Perl as shown



                      perl -lne '
                      next unless /foo/ ... /bar/;
                      push(@A, $_),next if !/foo/ && !/bar/ && !eof;
                      push(@A, $_) if !/foo/ && !/bar/ && eof;
                      print join " ", splice @A if /bar/ || !/foo/ && eof;
                      ' input-file.txt


                      Explanation:



                      • skip non-interesting lines or lines that fall out of range. A range is defined as beginning with a line containing /foo/ and ending with /bar/, both occurring on separate lines.

                      • Once we are in the range, then perform separate actions based on what line we are in.

                      • For lines that are not /foo/, neither /bar/, and neither eof : store the line in the array @A. After storing, go back for reading the next record provided not eof.

                      • Only for the end of range, i.e., /bar/ or eof, we take the action of printing what's in @A and also emptying it, in preparation for the next gathering cycle.





                      share|improve this answer


























                        up vote
                        2
                        down vote













                        You could do this way also:



                        a) This is POSIX-sed compliant code wherein we store the mid-range lines (!/foo/ and !/bar/) in the hold area.



                        sed -e '
                        /foo/,/bar/!d
                        /foo/d
                        /bar/!H;$!d;
                        s/.*//;x;s/^n//;y/n/ /
                        ' input-file.txt


                        b) and with Perl as shown



                        perl -lne '
                        next unless /foo/ ... /bar/;
                        push(@A, $_),next if !/foo/ && !/bar/ && !eof;
                        push(@A, $_) if !/foo/ && !/bar/ && eof;
                        print join " ", splice @A if /bar/ || !/foo/ && eof;
                        ' input-file.txt


                        Explanation:



                        • skip non-interesting lines or lines that fall out of range. A range is defined as beginning with a line containing /foo/ and ending with /bar/, both occurring on separate lines.

                        • Once we are in the range, then perform separate actions based on what line we are in.

                        • For lines that are not /foo/, neither /bar/, and neither eof : store the line in the array @A. After storing, go back for reading the next record provided not eof.

                        • Only for the end of range, i.e., /bar/ or eof, we take the action of printing what's in @A and also emptying it, in preparation for the next gathering cycle.





                        share|improve this answer
























                          up vote
                          2
                          down vote










                          up vote
                          2
                          down vote









                          You could do this way also:



                          a) This is POSIX-sed compliant code wherein we store the mid-range lines (!/foo/ and !/bar/) in the hold area.



                          sed -e '
                          /foo/,/bar/!d
                          /foo/d
                          /bar/!H;$!d;
                          s/.*//;x;s/^n//;y/n/ /
                          ' input-file.txt


                          b) and with Perl as shown



                          perl -lne '
                          next unless /foo/ ... /bar/;
                          push(@A, $_),next if !/foo/ && !/bar/ && !eof;
                          push(@A, $_) if !/foo/ && !/bar/ && eof;
                          print join " ", splice @A if /bar/ || !/foo/ && eof;
                          ' input-file.txt


                          Explanation:



                          • skip non-interesting lines or lines that fall out of range. A range is defined as beginning with a line containing /foo/ and ending with /bar/, both occurring on separate lines.

                          • Once we are in the range, then perform separate actions based on what line we are in.

                          • For lines that are not /foo/, neither /bar/, and neither eof : store the line in the array @A. After storing, go back for reading the next record provided not eof.

                          • Only for the end of range, i.e., /bar/ or eof, we take the action of printing what's in @A and also emptying it, in preparation for the next gathering cycle.





                          share|improve this answer














                          You could do this way also:



                          a) This is POSIX-sed compliant code wherein we store the mid-range lines (!/foo/ and !/bar/) in the hold area.



                          sed -e '
                          /foo/,/bar/!d
                          /foo/d
                          /bar/!H;$!d;
                          s/.*//;x;s/^n//;y/n/ /
                          ' input-file.txt


                          b) and with Perl as shown



                          perl -lne '
                          next unless /foo/ ... /bar/;
                          push(@A, $_),next if !/foo/ && !/bar/ && !eof;
                          push(@A, $_) if !/foo/ && !/bar/ && eof;
                          print join " ", splice @A if /bar/ || !/foo/ && eof;
                          ' input-file.txt


                          Explanation:



                          • skip non-interesting lines or lines that fall out of range. A range is defined as beginning with a line containing /foo/ and ending with /bar/, both occurring on separate lines.

                          • Once we are in the range, then perform separate actions based on what line we are in.

                          • For lines that are not /foo/, neither /bar/, and neither eof : store the line in the array @A. After storing, go back for reading the next record provided not eof.

                          • Only for the end of range, i.e., /bar/ or eof, we take the action of printing what's in @A and also emptying it, in preparation for the next gathering cycle.






                          share|improve this answer














                          share|improve this answer



                          share|improve this answer








                          edited Sep 18 at 13:47

























                          answered Sep 17 at 8:26









                          Rakesh Sharma

                          64513




                          64513



























                               

                              draft saved


                              draft discarded















































                               


                              draft saved


                              draft discarded














                              StackExchange.ready(
                              function ()
                              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f469458%2fdelete-newline-characters-between-patterns%23new-answer', 'question_page');

                              );

                              Post as a guest













































































                              Popular posts from this blog

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

                              Bahrain

                              Postfix configuration issue with fips on centos 7; mailgun relay