How to avoid redundant substitutes in sed?

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











up vote
0
down vote

favorite












1st file contains:



#. This is the file name to process: waveheight.txt
#. This is the latest data to process if exists: waveheightNew.txt
FilNam=Project2128/Input/waveheightNew.txt
if [[ ! -f $FilNam ]]; then FilNam=Project2128/Input/waveheight.txt; fi


2nd file contains:



#. This is the file name to process: waveheightBin.txt
#. This is the latest data to process if exists: waveheightNewBin.txt
FilNam=Project2128/Input/waveheightNewBin.txt
if [[ ! -f $FilNam ]]; then FilNam=Project2128/Input/waveheightBin.txt; fi


Now I need to process the files by changing .txt to Bin.txt?
Using sed "s/.txt/Bin.txt/" will lead to BinBin.txt for the 2nd file.
By sed "s/Bin.txt/.txt/" and then sed "s/.txt/Bin.txt/" seems awkward.



Would it be smarter to skip the unwanted matches?










share|improve this question



























    up vote
    0
    down vote

    favorite












    1st file contains:



    #. This is the file name to process: waveheight.txt
    #. This is the latest data to process if exists: waveheightNew.txt
    FilNam=Project2128/Input/waveheightNew.txt
    if [[ ! -f $FilNam ]]; then FilNam=Project2128/Input/waveheight.txt; fi


    2nd file contains:



    #. This is the file name to process: waveheightBin.txt
    #. This is the latest data to process if exists: waveheightNewBin.txt
    FilNam=Project2128/Input/waveheightNewBin.txt
    if [[ ! -f $FilNam ]]; then FilNam=Project2128/Input/waveheightBin.txt; fi


    Now I need to process the files by changing .txt to Bin.txt?
    Using sed "s/.txt/Bin.txt/" will lead to BinBin.txt for the 2nd file.
    By sed "s/Bin.txt/.txt/" and then sed "s/.txt/Bin.txt/" seems awkward.



    Would it be smarter to skip the unwanted matches?










    share|improve this question

























      up vote
      0
      down vote

      favorite









      up vote
      0
      down vote

      favorite











      1st file contains:



      #. This is the file name to process: waveheight.txt
      #. This is the latest data to process if exists: waveheightNew.txt
      FilNam=Project2128/Input/waveheightNew.txt
      if [[ ! -f $FilNam ]]; then FilNam=Project2128/Input/waveheight.txt; fi


      2nd file contains:



      #. This is the file name to process: waveheightBin.txt
      #. This is the latest data to process if exists: waveheightNewBin.txt
      FilNam=Project2128/Input/waveheightNewBin.txt
      if [[ ! -f $FilNam ]]; then FilNam=Project2128/Input/waveheightBin.txt; fi


      Now I need to process the files by changing .txt to Bin.txt?
      Using sed "s/.txt/Bin.txt/" will lead to BinBin.txt for the 2nd file.
      By sed "s/Bin.txt/.txt/" and then sed "s/.txt/Bin.txt/" seems awkward.



      Would it be smarter to skip the unwanted matches?










      share|improve this question















      1st file contains:



      #. This is the file name to process: waveheight.txt
      #. This is the latest data to process if exists: waveheightNew.txt
      FilNam=Project2128/Input/waveheightNew.txt
      if [[ ! -f $FilNam ]]; then FilNam=Project2128/Input/waveheight.txt; fi


      2nd file contains:



      #. This is the file name to process: waveheightBin.txt
      #. This is the latest data to process if exists: waveheightNewBin.txt
      FilNam=Project2128/Input/waveheightNewBin.txt
      if [[ ! -f $FilNam ]]; then FilNam=Project2128/Input/waveheightBin.txt; fi


      Now I need to process the files by changing .txt to Bin.txt?
      Using sed "s/.txt/Bin.txt/" will lead to BinBin.txt for the 2nd file.
      By sed "s/Bin.txt/.txt/" and then sed "s/.txt/Bin.txt/" seems awkward.



      Would it be smarter to skip the unwanted matches?







      sed






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Sep 19 at 7:03









      Sparhawk

      8,53863489




      8,53863489










      asked Sep 19 at 6:56









      MathArt

      32




      32




















          4 Answers
          4






          active

          oldest

          votes

















          up vote
          3
          down vote



          accepted










          You could include the Bin in the text to replace if there which would then result in it being replaced with itself:



          sed 's/(Bin)0,1.txt/Bin.txt/g'


          Or if your sed supports EREs with -E (or -r for some older versions of GNU or busybox sed):



          sed -E 's/(Bin)?.txt/Bin.txt/g'


          Beware . is a regexp operator that matches any single character. You need . to match a literal dot.






          share|improve this answer





























            up vote
            2
            down vote













            You can use a perl negative lookbehind to match .txt, but only it it's not Bin.txt.



            perl -pe 's/(?<!Bin).txt/Bin.txt/g'


            Hence, to test:



            $ echo 'Bin.txt foo.txt' | perl -pe 's/(?<!Bin).txt/Bin.txt/g'
            Bin.txt fooBin.txt


            Unfortunately, sed does not offer this construct.






            share|improve this answer






















            • Depends on the sed implementation, ssed supports it with -R and ast-open sed with -E/-r or -A/-X.
              – Stéphane Chazelas
              Sep 19 at 7:23


















            up vote
            1
            down vote













            You may do a conditional substitution with sed, for example, you may test whether the line already contains Bin.txt and only perform the substitution if it doesn't.



            sed '/Bin.txt/!s/.txt/Bin.txt/'


            This assumes that there will only be need for one substitution per line.



            You may also do the substitution unconditionally, and then correct it if it went wrong, as you hinted at in the question, but in the same call to sed:



            sed -e 's/.txt/Bin.txt/' -e 's/BinBin/Bin/'





            share|improve this answer





























              up vote
              0
              down vote













              You could do this with GNU-sed as shown:



              echo "$Filnam" |
              sed -e '
              s/.txt/n&/;T # try to place a newline marker to the left of .txt, quit if unsuccessful
              s/Binn/Bin/;t # If the marker turned out to be just to the right of Bin => Bin.txt already
              # existed in the name, so we needn"t do anything n take away the marker n quit
              s/n/Bin/ # Bin could not be found adjacent to .txt so put it n take away the marker as well
              '

              ### Below is the POSIX sed code for accomplishing the same:
              sed -e '
              s/.txt/
              &/;/n/!b
              s/Binn/Bin/;/n/!b
              s/n/Bin/
              '





              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%2f469939%2fhow-to-avoid-redundant-substitutes-in-sed%23new-answer', 'question_page');

                );

                Post as a guest






























                4 Answers
                4






                active

                oldest

                votes








                4 Answers
                4






                active

                oldest

                votes









                active

                oldest

                votes






                active

                oldest

                votes








                up vote
                3
                down vote



                accepted










                You could include the Bin in the text to replace if there which would then result in it being replaced with itself:



                sed 's/(Bin)0,1.txt/Bin.txt/g'


                Or if your sed supports EREs with -E (or -r for some older versions of GNU or busybox sed):



                sed -E 's/(Bin)?.txt/Bin.txt/g'


                Beware . is a regexp operator that matches any single character. You need . to match a literal dot.






                share|improve this answer


























                  up vote
                  3
                  down vote



                  accepted










                  You could include the Bin in the text to replace if there which would then result in it being replaced with itself:



                  sed 's/(Bin)0,1.txt/Bin.txt/g'


                  Or if your sed supports EREs with -E (or -r for some older versions of GNU or busybox sed):



                  sed -E 's/(Bin)?.txt/Bin.txt/g'


                  Beware . is a regexp operator that matches any single character. You need . to match a literal dot.






                  share|improve this answer
























                    up vote
                    3
                    down vote



                    accepted







                    up vote
                    3
                    down vote



                    accepted






                    You could include the Bin in the text to replace if there which would then result in it being replaced with itself:



                    sed 's/(Bin)0,1.txt/Bin.txt/g'


                    Or if your sed supports EREs with -E (or -r for some older versions of GNU or busybox sed):



                    sed -E 's/(Bin)?.txt/Bin.txt/g'


                    Beware . is a regexp operator that matches any single character. You need . to match a literal dot.






                    share|improve this answer














                    You could include the Bin in the text to replace if there which would then result in it being replaced with itself:



                    sed 's/(Bin)0,1.txt/Bin.txt/g'


                    Or if your sed supports EREs with -E (or -r for some older versions of GNU or busybox sed):



                    sed -E 's/(Bin)?.txt/Bin.txt/g'


                    Beware . is a regexp operator that matches any single character. You need . to match a literal dot.







                    share|improve this answer














                    share|improve this answer



                    share|improve this answer








                    edited Sep 19 at 10:11

























                    answered Sep 19 at 7:17









                    Stéphane Chazelas

                    287k53528867




                    287k53528867






















                        up vote
                        2
                        down vote













                        You can use a perl negative lookbehind to match .txt, but only it it's not Bin.txt.



                        perl -pe 's/(?<!Bin).txt/Bin.txt/g'


                        Hence, to test:



                        $ echo 'Bin.txt foo.txt' | perl -pe 's/(?<!Bin).txt/Bin.txt/g'
                        Bin.txt fooBin.txt


                        Unfortunately, sed does not offer this construct.






                        share|improve this answer






















                        • Depends on the sed implementation, ssed supports it with -R and ast-open sed with -E/-r or -A/-X.
                          – Stéphane Chazelas
                          Sep 19 at 7:23















                        up vote
                        2
                        down vote













                        You can use a perl negative lookbehind to match .txt, but only it it's not Bin.txt.



                        perl -pe 's/(?<!Bin).txt/Bin.txt/g'


                        Hence, to test:



                        $ echo 'Bin.txt foo.txt' | perl -pe 's/(?<!Bin).txt/Bin.txt/g'
                        Bin.txt fooBin.txt


                        Unfortunately, sed does not offer this construct.






                        share|improve this answer






















                        • Depends on the sed implementation, ssed supports it with -R and ast-open sed with -E/-r or -A/-X.
                          – Stéphane Chazelas
                          Sep 19 at 7:23













                        up vote
                        2
                        down vote










                        up vote
                        2
                        down vote









                        You can use a perl negative lookbehind to match .txt, but only it it's not Bin.txt.



                        perl -pe 's/(?<!Bin).txt/Bin.txt/g'


                        Hence, to test:



                        $ echo 'Bin.txt foo.txt' | perl -pe 's/(?<!Bin).txt/Bin.txt/g'
                        Bin.txt fooBin.txt


                        Unfortunately, sed does not offer this construct.






                        share|improve this answer














                        You can use a perl negative lookbehind to match .txt, but only it it's not Bin.txt.



                        perl -pe 's/(?<!Bin).txt/Bin.txt/g'


                        Hence, to test:



                        $ echo 'Bin.txt foo.txt' | perl -pe 's/(?<!Bin).txt/Bin.txt/g'
                        Bin.txt fooBin.txt


                        Unfortunately, sed does not offer this construct.







                        share|improve this answer














                        share|improve this answer



                        share|improve this answer








                        edited Sep 19 at 8:17

























                        answered Sep 19 at 7:14









                        Sparhawk

                        8,53863489




                        8,53863489











                        • Depends on the sed implementation, ssed supports it with -R and ast-open sed with -E/-r or -A/-X.
                          – Stéphane Chazelas
                          Sep 19 at 7:23

















                        • Depends on the sed implementation, ssed supports it with -R and ast-open sed with -E/-r or -A/-X.
                          – Stéphane Chazelas
                          Sep 19 at 7:23
















                        Depends on the sed implementation, ssed supports it with -R and ast-open sed with -E/-r or -A/-X.
                        – Stéphane Chazelas
                        Sep 19 at 7:23





                        Depends on the sed implementation, ssed supports it with -R and ast-open sed with -E/-r or -A/-X.
                        – Stéphane Chazelas
                        Sep 19 at 7:23











                        up vote
                        1
                        down vote













                        You may do a conditional substitution with sed, for example, you may test whether the line already contains Bin.txt and only perform the substitution if it doesn't.



                        sed '/Bin.txt/!s/.txt/Bin.txt/'


                        This assumes that there will only be need for one substitution per line.



                        You may also do the substitution unconditionally, and then correct it if it went wrong, as you hinted at in the question, but in the same call to sed:



                        sed -e 's/.txt/Bin.txt/' -e 's/BinBin/Bin/'





                        share|improve this answer


























                          up vote
                          1
                          down vote













                          You may do a conditional substitution with sed, for example, you may test whether the line already contains Bin.txt and only perform the substitution if it doesn't.



                          sed '/Bin.txt/!s/.txt/Bin.txt/'


                          This assumes that there will only be need for one substitution per line.



                          You may also do the substitution unconditionally, and then correct it if it went wrong, as you hinted at in the question, but in the same call to sed:



                          sed -e 's/.txt/Bin.txt/' -e 's/BinBin/Bin/'





                          share|improve this answer
























                            up vote
                            1
                            down vote










                            up vote
                            1
                            down vote









                            You may do a conditional substitution with sed, for example, you may test whether the line already contains Bin.txt and only perform the substitution if it doesn't.



                            sed '/Bin.txt/!s/.txt/Bin.txt/'


                            This assumes that there will only be need for one substitution per line.



                            You may also do the substitution unconditionally, and then correct it if it went wrong, as you hinted at in the question, but in the same call to sed:



                            sed -e 's/.txt/Bin.txt/' -e 's/BinBin/Bin/'





                            share|improve this answer














                            You may do a conditional substitution with sed, for example, you may test whether the line already contains Bin.txt and only perform the substitution if it doesn't.



                            sed '/Bin.txt/!s/.txt/Bin.txt/'


                            This assumes that there will only be need for one substitution per line.



                            You may also do the substitution unconditionally, and then correct it if it went wrong, as you hinted at in the question, but in the same call to sed:



                            sed -e 's/.txt/Bin.txt/' -e 's/BinBin/Bin/'






                            share|improve this answer














                            share|improve this answer



                            share|improve this answer








                            edited Sep 19 at 10:26

























                            answered Sep 19 at 7:10









                            Kusalananda

                            108k14209332




                            108k14209332




















                                up vote
                                0
                                down vote













                                You could do this with GNU-sed as shown:



                                echo "$Filnam" |
                                sed -e '
                                s/.txt/n&/;T # try to place a newline marker to the left of .txt, quit if unsuccessful
                                s/Binn/Bin/;t # If the marker turned out to be just to the right of Bin => Bin.txt already
                                # existed in the name, so we needn"t do anything n take away the marker n quit
                                s/n/Bin/ # Bin could not be found adjacent to .txt so put it n take away the marker as well
                                '

                                ### Below is the POSIX sed code for accomplishing the same:
                                sed -e '
                                s/.txt/
                                &/;/n/!b
                                s/Binn/Bin/;/n/!b
                                s/n/Bin/
                                '





                                share|improve this answer
























                                  up vote
                                  0
                                  down vote













                                  You could do this with GNU-sed as shown:



                                  echo "$Filnam" |
                                  sed -e '
                                  s/.txt/n&/;T # try to place a newline marker to the left of .txt, quit if unsuccessful
                                  s/Binn/Bin/;t # If the marker turned out to be just to the right of Bin => Bin.txt already
                                  # existed in the name, so we needn"t do anything n take away the marker n quit
                                  s/n/Bin/ # Bin could not be found adjacent to .txt so put it n take away the marker as well
                                  '

                                  ### Below is the POSIX sed code for accomplishing the same:
                                  sed -e '
                                  s/.txt/
                                  &/;/n/!b
                                  s/Binn/Bin/;/n/!b
                                  s/n/Bin/
                                  '





                                  share|improve this answer






















                                    up vote
                                    0
                                    down vote










                                    up vote
                                    0
                                    down vote









                                    You could do this with GNU-sed as shown:



                                    echo "$Filnam" |
                                    sed -e '
                                    s/.txt/n&/;T # try to place a newline marker to the left of .txt, quit if unsuccessful
                                    s/Binn/Bin/;t # If the marker turned out to be just to the right of Bin => Bin.txt already
                                    # existed in the name, so we needn"t do anything n take away the marker n quit
                                    s/n/Bin/ # Bin could not be found adjacent to .txt so put it n take away the marker as well
                                    '

                                    ### Below is the POSIX sed code for accomplishing the same:
                                    sed -e '
                                    s/.txt/
                                    &/;/n/!b
                                    s/Binn/Bin/;/n/!b
                                    s/n/Bin/
                                    '





                                    share|improve this answer












                                    You could do this with GNU-sed as shown:



                                    echo "$Filnam" |
                                    sed -e '
                                    s/.txt/n&/;T # try to place a newline marker to the left of .txt, quit if unsuccessful
                                    s/Binn/Bin/;t # If the marker turned out to be just to the right of Bin => Bin.txt already
                                    # existed in the name, so we needn"t do anything n take away the marker n quit
                                    s/n/Bin/ # Bin could not be found adjacent to .txt so put it n take away the marker as well
                                    '

                                    ### Below is the POSIX sed code for accomplishing the same:
                                    sed -e '
                                    s/.txt/
                                    &/;/n/!b
                                    s/Binn/Bin/;/n/!b
                                    s/n/Bin/
                                    '






                                    share|improve this answer












                                    share|improve this answer



                                    share|improve this answer










                                    answered Sep 20 at 4:56









                                    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%2f469939%2fhow-to-avoid-redundant-substitutes-in-sed%23new-answer', 'question_page');

                                        );

                                        Post as a guest













































































                                        Popular posts from this blog

                                        Peggy Mitchell

                                        The Forum (Inglewood, California)

                                        Palaiologos