Adding text to a file 2 lines before the last pattern match











up vote
1
down vote

favorite












I need to add a the multi line string in TEXT into myfile.txt where it last find the text # My Search.



If it was a regular pattern replace then sed with i would do the trick. However I don't know how to go 2 lines above the match in sed.



Example, myfile.txt:



text1
text2
#
# My Search
#
text4
text5
#
# My Search
#
text6


TEXT looks like:



TEXT="
[my search]
home=/var/home
string=random

"


myfile.txt should look at the end:



text1
text2
#
# My Search
#
text4
text5

[my search]
home=/var/home
string=random

#
# My Search
#
text6









share|improve this question




























    up vote
    1
    down vote

    favorite












    I need to add a the multi line string in TEXT into myfile.txt where it last find the text # My Search.



    If it was a regular pattern replace then sed with i would do the trick. However I don't know how to go 2 lines above the match in sed.



    Example, myfile.txt:



    text1
    text2
    #
    # My Search
    #
    text4
    text5
    #
    # My Search
    #
    text6


    TEXT looks like:



    TEXT="
    [my search]
    home=/var/home
    string=random

    "


    myfile.txt should look at the end:



    text1
    text2
    #
    # My Search
    #
    text4
    text5

    [my search]
    home=/var/home
    string=random

    #
    # My Search
    #
    text6









    share|improve this question


























      up vote
      1
      down vote

      favorite









      up vote
      1
      down vote

      favorite











      I need to add a the multi line string in TEXT into myfile.txt where it last find the text # My Search.



      If it was a regular pattern replace then sed with i would do the trick. However I don't know how to go 2 lines above the match in sed.



      Example, myfile.txt:



      text1
      text2
      #
      # My Search
      #
      text4
      text5
      #
      # My Search
      #
      text6


      TEXT looks like:



      TEXT="
      [my search]
      home=/var/home
      string=random

      "


      myfile.txt should look at the end:



      text1
      text2
      #
      # My Search
      #
      text4
      text5

      [my search]
      home=/var/home
      string=random

      #
      # My Search
      #
      text6









      share|improve this question















      I need to add a the multi line string in TEXT into myfile.txt where it last find the text # My Search.



      If it was a regular pattern replace then sed with i would do the trick. However I don't know how to go 2 lines above the match in sed.



      Example, myfile.txt:



      text1
      text2
      #
      # My Search
      #
      text4
      text5
      #
      # My Search
      #
      text6


      TEXT looks like:



      TEXT="
      [my search]
      home=/var/home
      string=random

      "


      myfile.txt should look at the end:



      text1
      text2
      #
      # My Search
      #
      text4
      text5

      [my search]
      home=/var/home
      string=random

      #
      # My Search
      #
      text6






      text-processing awk sed






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited 2 days ago









      don_crissti

      48.7k15129157




      48.7k15129157










      asked 2 days ago









      Nir

      43221020




      43221020






















          3 Answers
          3






          active

          oldest

          votes

















          up vote
          0
          down vote



          accepted










          Use grep -n to extract the line number, then use it in a sed address to insert the text, which needs to be properly quoted, i.e. there must be a backslash before each newline:



          line=$(grep -n '# My Search' myfile.txt | tail -n1 | cut -f1 -d:)
          ((--line))
          text=${TEXT//$'n'/$'\n'}
          text=${text%$'\n'}$'n'

          sed "$line i \
          $text" myfile.txt





          share|improve this answer




























            up vote
            0
            down vote













            tac + bash (variable substitution) + GNU sed approach:



            txt_reversed=$(echo "$TEXT" | tac)
            tac myfile.txt
            | sed -e "N;N;N; s~#n# My Searchn#~&${txt_reversed//$'n'/\n}n~" | tac


            The output:



            text1
            text2
            #
            # My Search
            #
            text4
            text5

            [my search]
            home=/var/home
            string=random

            #
            # My Search
            #
            text6





            share|improve this answer




























              up vote
              0
              down vote













              The easiest way to do this in one go is to use a tool that can search backward, ed is one of them. Ideally you would have the text saved in a file (e.g. insert.txt) and insert the file content two lines before the last occurrence of PATTERN so you could run:



              ed -s infile <<IN
              .t.
              ?PATTERN?-2r insert.txt
              $d
              ,p
              q
              IN


              It finds the last occurrence of PATTERN, goes up another 2 lines and reads in insert.txt. It then prints the content of the buffer via ,p. Replace that with w if you want to edit the file in-place.





              With other tools that can't search backward a two-pass is the way to go: 1st pass - get the line number and 2nd pass - insert the text content after line NR-2 or before line NR-1. For text saved in a variable I favor awk over other tools that rely on regex (the latter require pre-processing the text to be inserted so as to escape any special characters: there are several ones that need escaping, not just the newline, depending on the technique used):



              export TEXT
              awk 'NR==FNR{if ($0 ~ /PATTERN/){c=NR};next}
              {if (FNR==(c-1)){print ENVIRON["TEXT"]}};1' infile infile





              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%2f483150%2fadding-text-to-a-file-2-lines-before-the-last-pattern-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








                up vote
                0
                down vote



                accepted










                Use grep -n to extract the line number, then use it in a sed address to insert the text, which needs to be properly quoted, i.e. there must be a backslash before each newline:



                line=$(grep -n '# My Search' myfile.txt | tail -n1 | cut -f1 -d:)
                ((--line))
                text=${TEXT//$'n'/$'\n'}
                text=${text%$'\n'}$'n'

                sed "$line i \
                $text" myfile.txt





                share|improve this answer

























                  up vote
                  0
                  down vote



                  accepted










                  Use grep -n to extract the line number, then use it in a sed address to insert the text, which needs to be properly quoted, i.e. there must be a backslash before each newline:



                  line=$(grep -n '# My Search' myfile.txt | tail -n1 | cut -f1 -d:)
                  ((--line))
                  text=${TEXT//$'n'/$'\n'}
                  text=${text%$'\n'}$'n'

                  sed "$line i \
                  $text" myfile.txt





                  share|improve this answer























                    up vote
                    0
                    down vote



                    accepted







                    up vote
                    0
                    down vote



                    accepted






                    Use grep -n to extract the line number, then use it in a sed address to insert the text, which needs to be properly quoted, i.e. there must be a backslash before each newline:



                    line=$(grep -n '# My Search' myfile.txt | tail -n1 | cut -f1 -d:)
                    ((--line))
                    text=${TEXT//$'n'/$'\n'}
                    text=${text%$'\n'}$'n'

                    sed "$line i \
                    $text" myfile.txt





                    share|improve this answer












                    Use grep -n to extract the line number, then use it in a sed address to insert the text, which needs to be properly quoted, i.e. there must be a backslash before each newline:



                    line=$(grep -n '# My Search' myfile.txt | tail -n1 | cut -f1 -d:)
                    ((--line))
                    text=${TEXT//$'n'/$'\n'}
                    text=${text%$'\n'}$'n'

                    sed "$line i \
                    $text" myfile.txt






                    share|improve this answer












                    share|improve this answer



                    share|improve this answer










                    answered 2 days ago









                    choroba

                    25.8k44470




                    25.8k44470
























                        up vote
                        0
                        down vote













                        tac + bash (variable substitution) + GNU sed approach:



                        txt_reversed=$(echo "$TEXT" | tac)
                        tac myfile.txt
                        | sed -e "N;N;N; s~#n# My Searchn#~&${txt_reversed//$'n'/\n}n~" | tac


                        The output:



                        text1
                        text2
                        #
                        # My Search
                        #
                        text4
                        text5

                        [my search]
                        home=/var/home
                        string=random

                        #
                        # My Search
                        #
                        text6





                        share|improve this answer

























                          up vote
                          0
                          down vote













                          tac + bash (variable substitution) + GNU sed approach:



                          txt_reversed=$(echo "$TEXT" | tac)
                          tac myfile.txt
                          | sed -e "N;N;N; s~#n# My Searchn#~&${txt_reversed//$'n'/\n}n~" | tac


                          The output:



                          text1
                          text2
                          #
                          # My Search
                          #
                          text4
                          text5

                          [my search]
                          home=/var/home
                          string=random

                          #
                          # My Search
                          #
                          text6





                          share|improve this answer























                            up vote
                            0
                            down vote










                            up vote
                            0
                            down vote









                            tac + bash (variable substitution) + GNU sed approach:



                            txt_reversed=$(echo "$TEXT" | tac)
                            tac myfile.txt
                            | sed -e "N;N;N; s~#n# My Searchn#~&${txt_reversed//$'n'/\n}n~" | tac


                            The output:



                            text1
                            text2
                            #
                            # My Search
                            #
                            text4
                            text5

                            [my search]
                            home=/var/home
                            string=random

                            #
                            # My Search
                            #
                            text6





                            share|improve this answer












                            tac + bash (variable substitution) + GNU sed approach:



                            txt_reversed=$(echo "$TEXT" | tac)
                            tac myfile.txt
                            | sed -e "N;N;N; s~#n# My Searchn#~&${txt_reversed//$'n'/\n}n~" | tac


                            The output:



                            text1
                            text2
                            #
                            # My Search
                            #
                            text4
                            text5

                            [my search]
                            home=/var/home
                            string=random

                            #
                            # My Search
                            #
                            text6






                            share|improve this answer












                            share|improve this answer



                            share|improve this answer










                            answered 2 days ago









                            RomanPerekhrest

                            22.6k12246




                            22.6k12246






















                                up vote
                                0
                                down vote













                                The easiest way to do this in one go is to use a tool that can search backward, ed is one of them. Ideally you would have the text saved in a file (e.g. insert.txt) and insert the file content two lines before the last occurrence of PATTERN so you could run:



                                ed -s infile <<IN
                                .t.
                                ?PATTERN?-2r insert.txt
                                $d
                                ,p
                                q
                                IN


                                It finds the last occurrence of PATTERN, goes up another 2 lines and reads in insert.txt. It then prints the content of the buffer via ,p. Replace that with w if you want to edit the file in-place.





                                With other tools that can't search backward a two-pass is the way to go: 1st pass - get the line number and 2nd pass - insert the text content after line NR-2 or before line NR-1. For text saved in a variable I favor awk over other tools that rely on regex (the latter require pre-processing the text to be inserted so as to escape any special characters: there are several ones that need escaping, not just the newline, depending on the technique used):



                                export TEXT
                                awk 'NR==FNR{if ($0 ~ /PATTERN/){c=NR};next}
                                {if (FNR==(c-1)){print ENVIRON["TEXT"]}};1' infile infile





                                share|improve this answer

























                                  up vote
                                  0
                                  down vote













                                  The easiest way to do this in one go is to use a tool that can search backward, ed is one of them. Ideally you would have the text saved in a file (e.g. insert.txt) and insert the file content two lines before the last occurrence of PATTERN so you could run:



                                  ed -s infile <<IN
                                  .t.
                                  ?PATTERN?-2r insert.txt
                                  $d
                                  ,p
                                  q
                                  IN


                                  It finds the last occurrence of PATTERN, goes up another 2 lines and reads in insert.txt. It then prints the content of the buffer via ,p. Replace that with w if you want to edit the file in-place.





                                  With other tools that can't search backward a two-pass is the way to go: 1st pass - get the line number and 2nd pass - insert the text content after line NR-2 or before line NR-1. For text saved in a variable I favor awk over other tools that rely on regex (the latter require pre-processing the text to be inserted so as to escape any special characters: there are several ones that need escaping, not just the newline, depending on the technique used):



                                  export TEXT
                                  awk 'NR==FNR{if ($0 ~ /PATTERN/){c=NR};next}
                                  {if (FNR==(c-1)){print ENVIRON["TEXT"]}};1' infile infile





                                  share|improve this answer























                                    up vote
                                    0
                                    down vote










                                    up vote
                                    0
                                    down vote









                                    The easiest way to do this in one go is to use a tool that can search backward, ed is one of them. Ideally you would have the text saved in a file (e.g. insert.txt) and insert the file content two lines before the last occurrence of PATTERN so you could run:



                                    ed -s infile <<IN
                                    .t.
                                    ?PATTERN?-2r insert.txt
                                    $d
                                    ,p
                                    q
                                    IN


                                    It finds the last occurrence of PATTERN, goes up another 2 lines and reads in insert.txt. It then prints the content of the buffer via ,p. Replace that with w if you want to edit the file in-place.





                                    With other tools that can't search backward a two-pass is the way to go: 1st pass - get the line number and 2nd pass - insert the text content after line NR-2 or before line NR-1. For text saved in a variable I favor awk over other tools that rely on regex (the latter require pre-processing the text to be inserted so as to escape any special characters: there are several ones that need escaping, not just the newline, depending on the technique used):



                                    export TEXT
                                    awk 'NR==FNR{if ($0 ~ /PATTERN/){c=NR};next}
                                    {if (FNR==(c-1)){print ENVIRON["TEXT"]}};1' infile infile





                                    share|improve this answer












                                    The easiest way to do this in one go is to use a tool that can search backward, ed is one of them. Ideally you would have the text saved in a file (e.g. insert.txt) and insert the file content two lines before the last occurrence of PATTERN so you could run:



                                    ed -s infile <<IN
                                    .t.
                                    ?PATTERN?-2r insert.txt
                                    $d
                                    ,p
                                    q
                                    IN


                                    It finds the last occurrence of PATTERN, goes up another 2 lines and reads in insert.txt. It then prints the content of the buffer via ,p. Replace that with w if you want to edit the file in-place.





                                    With other tools that can't search backward a two-pass is the way to go: 1st pass - get the line number and 2nd pass - insert the text content after line NR-2 or before line NR-1. For text saved in a variable I favor awk over other tools that rely on regex (the latter require pre-processing the text to be inserted so as to escape any special characters: there are several ones that need escaping, not just the newline, depending on the technique used):



                                    export TEXT
                                    awk 'NR==FNR{if ($0 ~ /PATTERN/){c=NR};next}
                                    {if (FNR==(c-1)){print ENVIRON["TEXT"]}};1' infile infile






                                    share|improve this answer












                                    share|improve this answer



                                    share|improve this answer










                                    answered 2 days ago









                                    don_crissti

                                    48.7k15129157




                                    48.7k15129157






























                                         

                                        draft saved


                                        draft discarded



















































                                         


                                        draft saved


                                        draft discarded














                                        StackExchange.ready(
                                        function () {
                                        StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f483150%2fadding-text-to-a-file-2-lines-before-the-last-pattern-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

                                        サソリ

                                        広島県道265号伴広島線

                                        Accessing regular linux commands in Huawei's Dopra Linux