Edit file based on existence of a string

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











up vote
4
down vote

favorite












I have an input file say file1 which appears as follows



WRITE=2
START=1
SMEAR=0
MIN=6
MAX=100


My problem is to search for the string SMEAR and if the string exists replace the entire line with SMEAR=-5. However, if the SMEAR does not exist, then I need to insert a new line SMEAR=-5. Ultimately the line SMEAR=-5 should appear only once.
I can replace the string using sed



 sed -i '/SMEAR/cSMEAR=-5' file1


Or I can insert the string as a new line



 sed -i '10i SMEAR=-5' file1


But how can I combine them based on the existence of the string in the file



EDIT:
Also it would be helpful if I can pass the value of SMEAR as a variable










share|improve this question



























    up vote
    4
    down vote

    favorite












    I have an input file say file1 which appears as follows



    WRITE=2
    START=1
    SMEAR=0
    MIN=6
    MAX=100


    My problem is to search for the string SMEAR and if the string exists replace the entire line with SMEAR=-5. However, if the SMEAR does not exist, then I need to insert a new line SMEAR=-5. Ultimately the line SMEAR=-5 should appear only once.
    I can replace the string using sed



     sed -i '/SMEAR/cSMEAR=-5' file1


    Or I can insert the string as a new line



     sed -i '10i SMEAR=-5' file1


    But how can I combine them based on the existence of the string in the file



    EDIT:
    Also it would be helpful if I can pass the value of SMEAR as a variable










    share|improve this question

























      up vote
      4
      down vote

      favorite









      up vote
      4
      down vote

      favorite











      I have an input file say file1 which appears as follows



      WRITE=2
      START=1
      SMEAR=0
      MIN=6
      MAX=100


      My problem is to search for the string SMEAR and if the string exists replace the entire line with SMEAR=-5. However, if the SMEAR does not exist, then I need to insert a new line SMEAR=-5. Ultimately the line SMEAR=-5 should appear only once.
      I can replace the string using sed



       sed -i '/SMEAR/cSMEAR=-5' file1


      Or I can insert the string as a new line



       sed -i '10i SMEAR=-5' file1


      But how can I combine them based on the existence of the string in the file



      EDIT:
      Also it would be helpful if I can pass the value of SMEAR as a variable










      share|improve this question















      I have an input file say file1 which appears as follows



      WRITE=2
      START=1
      SMEAR=0
      MIN=6
      MAX=100


      My problem is to search for the string SMEAR and if the string exists replace the entire line with SMEAR=-5. However, if the SMEAR does not exist, then I need to insert a new line SMEAR=-5. Ultimately the line SMEAR=-5 should appear only once.
      I can replace the string using sed



       sed -i '/SMEAR/cSMEAR=-5' file1


      Or I can insert the string as a new line



       sed -i '10i SMEAR=-5' file1


      But how can I combine them based on the existence of the string in the file



      EDIT:
      Also it would be helpful if I can pass the value of SMEAR as a variable







      text-processing sed






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited May 11 '16 at 23:21

























      asked May 11 '16 at 19:58









      WanderingMind

      295411




      295411




















          3 Answers
          3






          active

          oldest

          votes

















          up vote
          6
          down vote



          accepted










          It appears that the sequence of the lines doesn't matter for your use case. Given that, I would use ex and simply:



          1. Remove all instances of SMEAR;

          2. Insert the line you want.

          You can do this like so:



          printf '%sn' 'g/SMEAR/d' '$a' 'SMEAR=-5' . x | ex file.txt


          The first command is to globally delete all lines which match the regex /SMEAR/.



          The next command is to append after the last line ($) the line SMEAR=-5. The . ends the text to be appended.



          The x command saves changes and exits.



          Each command is terminated by a newline by using printf '%sn' to send them to ex.




          Also see this very similar solution which I wrote a while back on the vi/Vim stack exchange.




          To test the changes by printing the changed file to the command line without saving the changes, replace the x with the two commands %p 'q!' like so:



          printf '%sn' 'g/SMEAR/d' '$a' 'SMEAR=-5' . %p 'q!' | ex file.txt


          % means "entire buffer," which is what gets printed.



          q! means "quit, discarding changes."



          To save the changes into a new file, replace the %p with w newfile.txt like so:



          printf '%sn' 'g/SMEAR/d' '$a' 'SMEAR=-5' . 'w newfile.txt' 'q!' | ex file.txt


          This writes the modified buffer into newfile.txt.



          Alternatively you could do this at the start, to make a backup, and then save the changed file contents to the original location, file.txt, like so:



          printf '%sn' 'w file.txt.bak' 'g/SMEAR/d' '$a' 'SMEAR=-5' . x | ex file.txt



          Edit: Actually you don't need to use q!; simply omitting the x is enough to avoid saving changes. When ex gets an EOF on trying to read further input, it will exit, and will not save changes.






          share|improve this answer






















          • Is there a way to backup the original file. Something equivalent to -i.bkp in sed
            – WanderingMind
            May 11 '16 at 20:10






          • 2




            @WanderingMind sed '/SMEAR/d;$aSMEAR=-5 would be something like this ex method to which the (unportable) -i option could be included.
            – thrig
            May 11 '16 at 20:19






          • 1




            @thrig - that would fail if the last line matched though...
            – don_crissti
            May 11 '16 at 20:22











          • @WanderingMind, that's a good question; I've updated my answer to describe the ex method for doing this.
            – Wildcard
            May 11 '16 at 20:37










          • I'm unable to pass a variable as a value in this command. Can you tell me how is this done
            – WanderingMind
            May 11 '16 at 23:12

















          up vote
          5
          down vote













          You could try like this: if a line matches just copy it to the hold space then substitute the value.

          On the la$t line exchange hold space and pattern space then check if the latter is empty. If it's not empty, it means the substitution was already made so nothing to do. If it's empty, that means no match was found so replace the pattern space with SMEAR=-5 then append to the current line in the hold buffer. Finally, exchange again:



          sed '/SMEAR/h;s/.*/SMEAR=-5/;$x;/^$/s//SMEAR=-5/;H;x' infile


          The above is gnu sed syntax. Portable:



          sed '/SMEAR/
          h
          s/.*/SMEAR=-5/

          $
          x
          /^$/
          s//SMEAR=-5/
          H

          x
          ' infile


          Alternate way with ed:



          ed -s infile<<IN || printf %s\n SMEAR=-5 >> infile
          /SMEAR.*/s//SMEAR=-5/
          w
          q
          IN


          If no line matches pattern, ed will error out so the second command (printf...) will be executed to append the line to the file. Otherwise ed will edit the file in-place.




          If you have the value of SMEAR saved in variable e.g.



          var=-7


          you would run:



          sed '/SMEAR/h;s/.*/SMEAR='"$var"'/;$x;/^$/s//SMEAR='"$var"'/;H;x' infile


          or



          ed -s infile<<IN || printf %s\n "SMEAR=$var" >> infile
          /SMEAR.*/s//SMEAR=$var/
          w
          q
          IN





          share|improve this answer






















          • Hi can you tell me is there a way to pass the value of SMEAR as a variable. If I use $var and " " in above command, sed complains saying bad substitution
            – WanderingMind
            May 11 '16 at 23:25

















          up vote
          0
          down vote













          Or, implementing Wildcard’s idea
          (remove any/all existing line(s) that contain SMEAR,
          and then insert the line you want) with stone-age tools:



          (grep -v '^SMEAR=' file1; echo 'SMEAR=-5') > file1.tmp && cp file1.tmp file1 && rm file1.tmp


          or, if you aren’t concerned
          about preserving the attributes (e.g., permissions) of
          and hard links to file1, you could do



          (grep -v '^SMEAR=' file1; echo 'SMEAR=-5') > file1.tmp && mv file1.tmp file1


          or, if you have sponge, you could do



          (grep -v '^SMEAR=' file1; echo 'SMEAR=-5') | sponge file1





          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%2f282605%2fedit-file-based-on-existence-of-a-string%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
            6
            down vote



            accepted










            It appears that the sequence of the lines doesn't matter for your use case. Given that, I would use ex and simply:



            1. Remove all instances of SMEAR;

            2. Insert the line you want.

            You can do this like so:



            printf '%sn' 'g/SMEAR/d' '$a' 'SMEAR=-5' . x | ex file.txt


            The first command is to globally delete all lines which match the regex /SMEAR/.



            The next command is to append after the last line ($) the line SMEAR=-5. The . ends the text to be appended.



            The x command saves changes and exits.



            Each command is terminated by a newline by using printf '%sn' to send them to ex.




            Also see this very similar solution which I wrote a while back on the vi/Vim stack exchange.




            To test the changes by printing the changed file to the command line without saving the changes, replace the x with the two commands %p 'q!' like so:



            printf '%sn' 'g/SMEAR/d' '$a' 'SMEAR=-5' . %p 'q!' | ex file.txt


            % means "entire buffer," which is what gets printed.



            q! means "quit, discarding changes."



            To save the changes into a new file, replace the %p with w newfile.txt like so:



            printf '%sn' 'g/SMEAR/d' '$a' 'SMEAR=-5' . 'w newfile.txt' 'q!' | ex file.txt


            This writes the modified buffer into newfile.txt.



            Alternatively you could do this at the start, to make a backup, and then save the changed file contents to the original location, file.txt, like so:



            printf '%sn' 'w file.txt.bak' 'g/SMEAR/d' '$a' 'SMEAR=-5' . x | ex file.txt



            Edit: Actually you don't need to use q!; simply omitting the x is enough to avoid saving changes. When ex gets an EOF on trying to read further input, it will exit, and will not save changes.






            share|improve this answer






















            • Is there a way to backup the original file. Something equivalent to -i.bkp in sed
              – WanderingMind
              May 11 '16 at 20:10






            • 2




              @WanderingMind sed '/SMEAR/d;$aSMEAR=-5 would be something like this ex method to which the (unportable) -i option could be included.
              – thrig
              May 11 '16 at 20:19






            • 1




              @thrig - that would fail if the last line matched though...
              – don_crissti
              May 11 '16 at 20:22











            • @WanderingMind, that's a good question; I've updated my answer to describe the ex method for doing this.
              – Wildcard
              May 11 '16 at 20:37










            • I'm unable to pass a variable as a value in this command. Can you tell me how is this done
              – WanderingMind
              May 11 '16 at 23:12














            up vote
            6
            down vote



            accepted










            It appears that the sequence of the lines doesn't matter for your use case. Given that, I would use ex and simply:



            1. Remove all instances of SMEAR;

            2. Insert the line you want.

            You can do this like so:



            printf '%sn' 'g/SMEAR/d' '$a' 'SMEAR=-5' . x | ex file.txt


            The first command is to globally delete all lines which match the regex /SMEAR/.



            The next command is to append after the last line ($) the line SMEAR=-5. The . ends the text to be appended.



            The x command saves changes and exits.



            Each command is terminated by a newline by using printf '%sn' to send them to ex.




            Also see this very similar solution which I wrote a while back on the vi/Vim stack exchange.




            To test the changes by printing the changed file to the command line without saving the changes, replace the x with the two commands %p 'q!' like so:



            printf '%sn' 'g/SMEAR/d' '$a' 'SMEAR=-5' . %p 'q!' | ex file.txt


            % means "entire buffer," which is what gets printed.



            q! means "quit, discarding changes."



            To save the changes into a new file, replace the %p with w newfile.txt like so:



            printf '%sn' 'g/SMEAR/d' '$a' 'SMEAR=-5' . 'w newfile.txt' 'q!' | ex file.txt


            This writes the modified buffer into newfile.txt.



            Alternatively you could do this at the start, to make a backup, and then save the changed file contents to the original location, file.txt, like so:



            printf '%sn' 'w file.txt.bak' 'g/SMEAR/d' '$a' 'SMEAR=-5' . x | ex file.txt



            Edit: Actually you don't need to use q!; simply omitting the x is enough to avoid saving changes. When ex gets an EOF on trying to read further input, it will exit, and will not save changes.






            share|improve this answer






















            • Is there a way to backup the original file. Something equivalent to -i.bkp in sed
              – WanderingMind
              May 11 '16 at 20:10






            • 2




              @WanderingMind sed '/SMEAR/d;$aSMEAR=-5 would be something like this ex method to which the (unportable) -i option could be included.
              – thrig
              May 11 '16 at 20:19






            • 1




              @thrig - that would fail if the last line matched though...
              – don_crissti
              May 11 '16 at 20:22











            • @WanderingMind, that's a good question; I've updated my answer to describe the ex method for doing this.
              – Wildcard
              May 11 '16 at 20:37










            • I'm unable to pass a variable as a value in this command. Can you tell me how is this done
              – WanderingMind
              May 11 '16 at 23:12












            up vote
            6
            down vote



            accepted







            up vote
            6
            down vote



            accepted






            It appears that the sequence of the lines doesn't matter for your use case. Given that, I would use ex and simply:



            1. Remove all instances of SMEAR;

            2. Insert the line you want.

            You can do this like so:



            printf '%sn' 'g/SMEAR/d' '$a' 'SMEAR=-5' . x | ex file.txt


            The first command is to globally delete all lines which match the regex /SMEAR/.



            The next command is to append after the last line ($) the line SMEAR=-5. The . ends the text to be appended.



            The x command saves changes and exits.



            Each command is terminated by a newline by using printf '%sn' to send them to ex.




            Also see this very similar solution which I wrote a while back on the vi/Vim stack exchange.




            To test the changes by printing the changed file to the command line without saving the changes, replace the x with the two commands %p 'q!' like so:



            printf '%sn' 'g/SMEAR/d' '$a' 'SMEAR=-5' . %p 'q!' | ex file.txt


            % means "entire buffer," which is what gets printed.



            q! means "quit, discarding changes."



            To save the changes into a new file, replace the %p with w newfile.txt like so:



            printf '%sn' 'g/SMEAR/d' '$a' 'SMEAR=-5' . 'w newfile.txt' 'q!' | ex file.txt


            This writes the modified buffer into newfile.txt.



            Alternatively you could do this at the start, to make a backup, and then save the changed file contents to the original location, file.txt, like so:



            printf '%sn' 'w file.txt.bak' 'g/SMEAR/d' '$a' 'SMEAR=-5' . x | ex file.txt



            Edit: Actually you don't need to use q!; simply omitting the x is enough to avoid saving changes. When ex gets an EOF on trying to read further input, it will exit, and will not save changes.






            share|improve this answer














            It appears that the sequence of the lines doesn't matter for your use case. Given that, I would use ex and simply:



            1. Remove all instances of SMEAR;

            2. Insert the line you want.

            You can do this like so:



            printf '%sn' 'g/SMEAR/d' '$a' 'SMEAR=-5' . x | ex file.txt


            The first command is to globally delete all lines which match the regex /SMEAR/.



            The next command is to append after the last line ($) the line SMEAR=-5. The . ends the text to be appended.



            The x command saves changes and exits.



            Each command is terminated by a newline by using printf '%sn' to send them to ex.




            Also see this very similar solution which I wrote a while back on the vi/Vim stack exchange.




            To test the changes by printing the changed file to the command line without saving the changes, replace the x with the two commands %p 'q!' like so:



            printf '%sn' 'g/SMEAR/d' '$a' 'SMEAR=-5' . %p 'q!' | ex file.txt


            % means "entire buffer," which is what gets printed.



            q! means "quit, discarding changes."



            To save the changes into a new file, replace the %p with w newfile.txt like so:



            printf '%sn' 'g/SMEAR/d' '$a' 'SMEAR=-5' . 'w newfile.txt' 'q!' | ex file.txt


            This writes the modified buffer into newfile.txt.



            Alternatively you could do this at the start, to make a backup, and then save the changed file contents to the original location, file.txt, like so:



            printf '%sn' 'w file.txt.bak' 'g/SMEAR/d' '$a' 'SMEAR=-5' . x | ex file.txt



            Edit: Actually you don't need to use q!; simply omitting the x is enough to avoid saving changes. When ex gets an EOF on trying to read further input, it will exit, and will not save changes.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Jan 19 at 2:02

























            answered May 11 '16 at 20:03









            Wildcard

            22.4k959162




            22.4k959162











            • Is there a way to backup the original file. Something equivalent to -i.bkp in sed
              – WanderingMind
              May 11 '16 at 20:10






            • 2




              @WanderingMind sed '/SMEAR/d;$aSMEAR=-5 would be something like this ex method to which the (unportable) -i option could be included.
              – thrig
              May 11 '16 at 20:19






            • 1




              @thrig - that would fail if the last line matched though...
              – don_crissti
              May 11 '16 at 20:22











            • @WanderingMind, that's a good question; I've updated my answer to describe the ex method for doing this.
              – Wildcard
              May 11 '16 at 20:37










            • I'm unable to pass a variable as a value in this command. Can you tell me how is this done
              – WanderingMind
              May 11 '16 at 23:12
















            • Is there a way to backup the original file. Something equivalent to -i.bkp in sed
              – WanderingMind
              May 11 '16 at 20:10






            • 2




              @WanderingMind sed '/SMEAR/d;$aSMEAR=-5 would be something like this ex method to which the (unportable) -i option could be included.
              – thrig
              May 11 '16 at 20:19






            • 1




              @thrig - that would fail if the last line matched though...
              – don_crissti
              May 11 '16 at 20:22











            • @WanderingMind, that's a good question; I've updated my answer to describe the ex method for doing this.
              – Wildcard
              May 11 '16 at 20:37










            • I'm unable to pass a variable as a value in this command. Can you tell me how is this done
              – WanderingMind
              May 11 '16 at 23:12















            Is there a way to backup the original file. Something equivalent to -i.bkp in sed
            – WanderingMind
            May 11 '16 at 20:10




            Is there a way to backup the original file. Something equivalent to -i.bkp in sed
            – WanderingMind
            May 11 '16 at 20:10




            2




            2




            @WanderingMind sed '/SMEAR/d;$aSMEAR=-5 would be something like this ex method to which the (unportable) -i option could be included.
            – thrig
            May 11 '16 at 20:19




            @WanderingMind sed '/SMEAR/d;$aSMEAR=-5 would be something like this ex method to which the (unportable) -i option could be included.
            – thrig
            May 11 '16 at 20:19




            1




            1




            @thrig - that would fail if the last line matched though...
            – don_crissti
            May 11 '16 at 20:22





            @thrig - that would fail if the last line matched though...
            – don_crissti
            May 11 '16 at 20:22













            @WanderingMind, that's a good question; I've updated my answer to describe the ex method for doing this.
            – Wildcard
            May 11 '16 at 20:37




            @WanderingMind, that's a good question; I've updated my answer to describe the ex method for doing this.
            – Wildcard
            May 11 '16 at 20:37












            I'm unable to pass a variable as a value in this command. Can you tell me how is this done
            – WanderingMind
            May 11 '16 at 23:12




            I'm unable to pass a variable as a value in this command. Can you tell me how is this done
            – WanderingMind
            May 11 '16 at 23:12












            up vote
            5
            down vote













            You could try like this: if a line matches just copy it to the hold space then substitute the value.

            On the la$t line exchange hold space and pattern space then check if the latter is empty. If it's not empty, it means the substitution was already made so nothing to do. If it's empty, that means no match was found so replace the pattern space with SMEAR=-5 then append to the current line in the hold buffer. Finally, exchange again:



            sed '/SMEAR/h;s/.*/SMEAR=-5/;$x;/^$/s//SMEAR=-5/;H;x' infile


            The above is gnu sed syntax. Portable:



            sed '/SMEAR/
            h
            s/.*/SMEAR=-5/

            $
            x
            /^$/
            s//SMEAR=-5/
            H

            x
            ' infile


            Alternate way with ed:



            ed -s infile<<IN || printf %s\n SMEAR=-5 >> infile
            /SMEAR.*/s//SMEAR=-5/
            w
            q
            IN


            If no line matches pattern, ed will error out so the second command (printf...) will be executed to append the line to the file. Otherwise ed will edit the file in-place.




            If you have the value of SMEAR saved in variable e.g.



            var=-7


            you would run:



            sed '/SMEAR/h;s/.*/SMEAR='"$var"'/;$x;/^$/s//SMEAR='"$var"'/;H;x' infile


            or



            ed -s infile<<IN || printf %s\n "SMEAR=$var" >> infile
            /SMEAR.*/s//SMEAR=$var/
            w
            q
            IN





            share|improve this answer






















            • Hi can you tell me is there a way to pass the value of SMEAR as a variable. If I use $var and " " in above command, sed complains saying bad substitution
              – WanderingMind
              May 11 '16 at 23:25














            up vote
            5
            down vote













            You could try like this: if a line matches just copy it to the hold space then substitute the value.

            On the la$t line exchange hold space and pattern space then check if the latter is empty. If it's not empty, it means the substitution was already made so nothing to do. If it's empty, that means no match was found so replace the pattern space with SMEAR=-5 then append to the current line in the hold buffer. Finally, exchange again:



            sed '/SMEAR/h;s/.*/SMEAR=-5/;$x;/^$/s//SMEAR=-5/;H;x' infile


            The above is gnu sed syntax. Portable:



            sed '/SMEAR/
            h
            s/.*/SMEAR=-5/

            $
            x
            /^$/
            s//SMEAR=-5/
            H

            x
            ' infile


            Alternate way with ed:



            ed -s infile<<IN || printf %s\n SMEAR=-5 >> infile
            /SMEAR.*/s//SMEAR=-5/
            w
            q
            IN


            If no line matches pattern, ed will error out so the second command (printf...) will be executed to append the line to the file. Otherwise ed will edit the file in-place.




            If you have the value of SMEAR saved in variable e.g.



            var=-7


            you would run:



            sed '/SMEAR/h;s/.*/SMEAR='"$var"'/;$x;/^$/s//SMEAR='"$var"'/;H;x' infile


            or



            ed -s infile<<IN || printf %s\n "SMEAR=$var" >> infile
            /SMEAR.*/s//SMEAR=$var/
            w
            q
            IN





            share|improve this answer






















            • Hi can you tell me is there a way to pass the value of SMEAR as a variable. If I use $var and " " in above command, sed complains saying bad substitution
              – WanderingMind
              May 11 '16 at 23:25












            up vote
            5
            down vote










            up vote
            5
            down vote









            You could try like this: if a line matches just copy it to the hold space then substitute the value.

            On the la$t line exchange hold space and pattern space then check if the latter is empty. If it's not empty, it means the substitution was already made so nothing to do. If it's empty, that means no match was found so replace the pattern space with SMEAR=-5 then append to the current line in the hold buffer. Finally, exchange again:



            sed '/SMEAR/h;s/.*/SMEAR=-5/;$x;/^$/s//SMEAR=-5/;H;x' infile


            The above is gnu sed syntax. Portable:



            sed '/SMEAR/
            h
            s/.*/SMEAR=-5/

            $
            x
            /^$/
            s//SMEAR=-5/
            H

            x
            ' infile


            Alternate way with ed:



            ed -s infile<<IN || printf %s\n SMEAR=-5 >> infile
            /SMEAR.*/s//SMEAR=-5/
            w
            q
            IN


            If no line matches pattern, ed will error out so the second command (printf...) will be executed to append the line to the file. Otherwise ed will edit the file in-place.




            If you have the value of SMEAR saved in variable e.g.



            var=-7


            you would run:



            sed '/SMEAR/h;s/.*/SMEAR='"$var"'/;$x;/^$/s//SMEAR='"$var"'/;H;x' infile


            or



            ed -s infile<<IN || printf %s\n "SMEAR=$var" >> infile
            /SMEAR.*/s//SMEAR=$var/
            w
            q
            IN





            share|improve this answer














            You could try like this: if a line matches just copy it to the hold space then substitute the value.

            On the la$t line exchange hold space and pattern space then check if the latter is empty. If it's not empty, it means the substitution was already made so nothing to do. If it's empty, that means no match was found so replace the pattern space with SMEAR=-5 then append to the current line in the hold buffer. Finally, exchange again:



            sed '/SMEAR/h;s/.*/SMEAR=-5/;$x;/^$/s//SMEAR=-5/;H;x' infile


            The above is gnu sed syntax. Portable:



            sed '/SMEAR/
            h
            s/.*/SMEAR=-5/

            $
            x
            /^$/
            s//SMEAR=-5/
            H

            x
            ' infile


            Alternate way with ed:



            ed -s infile<<IN || printf %s\n SMEAR=-5 >> infile
            /SMEAR.*/s//SMEAR=-5/
            w
            q
            IN


            If no line matches pattern, ed will error out so the second command (printf...) will be executed to append the line to the file. Otherwise ed will edit the file in-place.




            If you have the value of SMEAR saved in variable e.g.



            var=-7


            you would run:



            sed '/SMEAR/h;s/.*/SMEAR='"$var"'/;$x;/^$/s//SMEAR='"$var"'/;H;x' infile


            or



            ed -s infile<<IN || printf %s\n "SMEAR=$var" >> infile
            /SMEAR.*/s//SMEAR=$var/
            w
            q
            IN






            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited May 11 '16 at 23:35

























            answered May 11 '16 at 20:03









            don_crissti

            48.4k15128158




            48.4k15128158











            • Hi can you tell me is there a way to pass the value of SMEAR as a variable. If I use $var and " " in above command, sed complains saying bad substitution
              – WanderingMind
              May 11 '16 at 23:25
















            • Hi can you tell me is there a way to pass the value of SMEAR as a variable. If I use $var and " " in above command, sed complains saying bad substitution
              – WanderingMind
              May 11 '16 at 23:25















            Hi can you tell me is there a way to pass the value of SMEAR as a variable. If I use $var and " " in above command, sed complains saying bad substitution
            – WanderingMind
            May 11 '16 at 23:25




            Hi can you tell me is there a way to pass the value of SMEAR as a variable. If I use $var and " " in above command, sed complains saying bad substitution
            – WanderingMind
            May 11 '16 at 23:25










            up vote
            0
            down vote













            Or, implementing Wildcard’s idea
            (remove any/all existing line(s) that contain SMEAR,
            and then insert the line you want) with stone-age tools:



            (grep -v '^SMEAR=' file1; echo 'SMEAR=-5') > file1.tmp && cp file1.tmp file1 && rm file1.tmp


            or, if you aren’t concerned
            about preserving the attributes (e.g., permissions) of
            and hard links to file1, you could do



            (grep -v '^SMEAR=' file1; echo 'SMEAR=-5') > file1.tmp && mv file1.tmp file1


            or, if you have sponge, you could do



            (grep -v '^SMEAR=' file1; echo 'SMEAR=-5') | sponge file1





            share|improve this answer
























              up vote
              0
              down vote













              Or, implementing Wildcard’s idea
              (remove any/all existing line(s) that contain SMEAR,
              and then insert the line you want) with stone-age tools:



              (grep -v '^SMEAR=' file1; echo 'SMEAR=-5') > file1.tmp && cp file1.tmp file1 && rm file1.tmp


              or, if you aren’t concerned
              about preserving the attributes (e.g., permissions) of
              and hard links to file1, you could do



              (grep -v '^SMEAR=' file1; echo 'SMEAR=-5') > file1.tmp && mv file1.tmp file1


              or, if you have sponge, you could do



              (grep -v '^SMEAR=' file1; echo 'SMEAR=-5') | sponge file1





              share|improve this answer






















                up vote
                0
                down vote










                up vote
                0
                down vote









                Or, implementing Wildcard’s idea
                (remove any/all existing line(s) that contain SMEAR,
                and then insert the line you want) with stone-age tools:



                (grep -v '^SMEAR=' file1; echo 'SMEAR=-5') > file1.tmp && cp file1.tmp file1 && rm file1.tmp


                or, if you aren’t concerned
                about preserving the attributes (e.g., permissions) of
                and hard links to file1, you could do



                (grep -v '^SMEAR=' file1; echo 'SMEAR=-5') > file1.tmp && mv file1.tmp file1


                or, if you have sponge, you could do



                (grep -v '^SMEAR=' file1; echo 'SMEAR=-5') | sponge file1





                share|improve this answer












                Or, implementing Wildcard’s idea
                (remove any/all existing line(s) that contain SMEAR,
                and then insert the line you want) with stone-age tools:



                (grep -v '^SMEAR=' file1; echo 'SMEAR=-5') > file1.tmp && cp file1.tmp file1 && rm file1.tmp


                or, if you aren’t concerned
                about preserving the attributes (e.g., permissions) of
                and hard links to file1, you could do



                (grep -v '^SMEAR=' file1; echo 'SMEAR=-5') > file1.tmp && mv file1.tmp file1


                or, if you have sponge, you could do



                (grep -v '^SMEAR=' file1; echo 'SMEAR=-5') | sponge file1






                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered 16 mins ago









                G-Man

                12.2k92860




                12.2k92860



























                     

                    draft saved


                    draft discarded















































                     


                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function ()
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f282605%2fedit-file-based-on-existence-of-a-string%23new-answer', 'question_page');

                    );

                    Post as a guest













































































                    Popular posts from this blog

                    Peggy Mitchell

                    Palaiologos

                    The Forum (Inglewood, California)