Match a pattern and replace the first instance of string following it












4















I'm scripting the modification of a config file laid out like this:



[purple]
auth = no
enabled = 0
username =
password =
priority = 0
host = True

[shovel]
group =
manual = False
enabled = 0
username =


Where there are many [categories] and sometimes with the same key of a key/value pair.



Is it possible to craft a one-liner using awk/sed/grep/tr/cut/perl that can change the value of "enabled = 0" to "enabled = 1" but ONLY for the category [shovel]?










share|improve this question



























    4















    I'm scripting the modification of a config file laid out like this:



    [purple]
    auth = no
    enabled = 0
    username =
    password =
    priority = 0
    host = True

    [shovel]
    group =
    manual = False
    enabled = 0
    username =


    Where there are many [categories] and sometimes with the same key of a key/value pair.



    Is it possible to craft a one-liner using awk/sed/grep/tr/cut/perl that can change the value of "enabled = 0" to "enabled = 1" but ONLY for the category [shovel]?










    share|improve this question

























      4












      4








      4








      I'm scripting the modification of a config file laid out like this:



      [purple]
      auth = no
      enabled = 0
      username =
      password =
      priority = 0
      host = True

      [shovel]
      group =
      manual = False
      enabled = 0
      username =


      Where there are many [categories] and sometimes with the same key of a key/value pair.



      Is it possible to craft a one-liner using awk/sed/grep/tr/cut/perl that can change the value of "enabled = 0" to "enabled = 1" but ONLY for the category [shovel]?










      share|improve this question














      I'm scripting the modification of a config file laid out like this:



      [purple]
      auth = no
      enabled = 0
      username =
      password =
      priority = 0
      host = True

      [shovel]
      group =
      manual = False
      enabled = 0
      username =


      Where there are many [categories] and sometimes with the same key of a key/value pair.



      Is it possible to craft a one-liner using awk/sed/grep/tr/cut/perl that can change the value of "enabled = 0" to "enabled = 1" but ONLY for the category [shovel]?







      awk sed grep regular-expression perl






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Jan 27 '17 at 4:30









      user1930831user1930831

      255




      255






















          4 Answers
          4






          active

          oldest

          votes


















          5














          In sed you can use a range (stopping on the empty line at the end of the [shovel] category):



          sed '/[shovel]/,/^$/ s/enabled = 0/enabled = 1/' file


          the first part /[shovel]/,/^$/ means find a line with [shovel], keep going until you find an empty line, and do the following command(s) (in this case a simple s/old/new) only on that part of file



          Note in response to comment: sed will not accept alternative delimiters in ranges and addresses (so escape any / characters that must be literal, if you need to match them), unless they are preceded by a backslash. You can always use an alternative delimiter in any following commands, for example:



          sed '/[shovel]/,/^$/ s|enabled = 0|enabled = 1|' file


          Or



          sed '|[shovel]|, |^$| s|enabled = 0|enabled = 1|' file





          share|improve this answer


























          • Perfect. How would I change the delimiter? One of the values is a pathname so I'm trying to change the delimiter to a pipe. I've tried replacing all of the delimiters as well as just the two following the 's' and both error out. -sed -i "/[shovel]/,/^$/ s|home = .*|home = /home/test/" file gives me: sed: -e expression #1, char 48: unterminated 's' command and -sed -i "|[shovel]|,|^$| s|home = .*|home = /home/test/" file gives me: sed: -e expression #1, char 1: unknown command: '|'

            – user1930831
            Jan 27 '17 at 17:01













          • You just need to put the last delimiter in: sed '/[shovel]/,/^$/ s|enabled = 0|enabled = 1|' @user1930831 :)

            – Zanna
            Jan 27 '17 at 18:50



















          0














          Here's a solution using Perl, assuming your configuration is in config.ini:



          perl -000 -n -i -e 's/^enabled = 0$/enabled = 1/m if /^[shovel]n/; print;' config.ini


          This does the following:





          • -000 - Read file in paragraph mode, essentially the same as doing $/ = "nn"; in the code.


          • -n - Run the specified code inside a while (<>) { } loop.


          • -i - In-line edit the specified file instead of printing to standard output. You can optionally specify an extension, which will cause the input file to be backed up with that extension. For instance, -i.bak would create a backup file called config.ini.bak.


          • -e - Executes the specified perl code.


          The code itself says to replace lines containing exactly enabled = 0 with enabled = 1 if the input "paragraph" starts with [shovel] on a line by itself. The [ and ] have to be escaped since they normally have special meaning in a regular expression.






          share|improve this answer
























          • If you're using Perl, you could pick up the Config::IniFiles module and use that.

            – Kusalananda
            Jan 27 '17 at 8:01



















          0














          can you try this awk solution



          awk '/shovel/{flag=1}flag&&/enabled/{$NF=1;flag=0}1' input





          share|improve this answer































            0














            You can restrict sed to only modifying a particular line:



             sed -i '3s/enabled = 0/enabled = 1/g' file


            This will only modify the 3rd line for [purple]






            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',
              autoActivateHeartbeat: false,
              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%2f340459%2fmatch-a-pattern-and-replace-the-first-instance-of-string-following-it%23new-answer', 'question_page');
              }
              );

              Post as a guest















              Required, but never shown

























              4 Answers
              4






              active

              oldest

              votes








              4 Answers
              4






              active

              oldest

              votes









              active

              oldest

              votes






              active

              oldest

              votes









              5














              In sed you can use a range (stopping on the empty line at the end of the [shovel] category):



              sed '/[shovel]/,/^$/ s/enabled = 0/enabled = 1/' file


              the first part /[shovel]/,/^$/ means find a line with [shovel], keep going until you find an empty line, and do the following command(s) (in this case a simple s/old/new) only on that part of file



              Note in response to comment: sed will not accept alternative delimiters in ranges and addresses (so escape any / characters that must be literal, if you need to match them), unless they are preceded by a backslash. You can always use an alternative delimiter in any following commands, for example:



              sed '/[shovel]/,/^$/ s|enabled = 0|enabled = 1|' file


              Or



              sed '|[shovel]|, |^$| s|enabled = 0|enabled = 1|' file





              share|improve this answer


























              • Perfect. How would I change the delimiter? One of the values is a pathname so I'm trying to change the delimiter to a pipe. I've tried replacing all of the delimiters as well as just the two following the 's' and both error out. -sed -i "/[shovel]/,/^$/ s|home = .*|home = /home/test/" file gives me: sed: -e expression #1, char 48: unterminated 's' command and -sed -i "|[shovel]|,|^$| s|home = .*|home = /home/test/" file gives me: sed: -e expression #1, char 1: unknown command: '|'

                – user1930831
                Jan 27 '17 at 17:01













              • You just need to put the last delimiter in: sed '/[shovel]/,/^$/ s|enabled = 0|enabled = 1|' @user1930831 :)

                – Zanna
                Jan 27 '17 at 18:50
















              5














              In sed you can use a range (stopping on the empty line at the end of the [shovel] category):



              sed '/[shovel]/,/^$/ s/enabled = 0/enabled = 1/' file


              the first part /[shovel]/,/^$/ means find a line with [shovel], keep going until you find an empty line, and do the following command(s) (in this case a simple s/old/new) only on that part of file



              Note in response to comment: sed will not accept alternative delimiters in ranges and addresses (so escape any / characters that must be literal, if you need to match them), unless they are preceded by a backslash. You can always use an alternative delimiter in any following commands, for example:



              sed '/[shovel]/,/^$/ s|enabled = 0|enabled = 1|' file


              Or



              sed '|[shovel]|, |^$| s|enabled = 0|enabled = 1|' file





              share|improve this answer


























              • Perfect. How would I change the delimiter? One of the values is a pathname so I'm trying to change the delimiter to a pipe. I've tried replacing all of the delimiters as well as just the two following the 's' and both error out. -sed -i "/[shovel]/,/^$/ s|home = .*|home = /home/test/" file gives me: sed: -e expression #1, char 48: unterminated 's' command and -sed -i "|[shovel]|,|^$| s|home = .*|home = /home/test/" file gives me: sed: -e expression #1, char 1: unknown command: '|'

                – user1930831
                Jan 27 '17 at 17:01













              • You just need to put the last delimiter in: sed '/[shovel]/,/^$/ s|enabled = 0|enabled = 1|' @user1930831 :)

                – Zanna
                Jan 27 '17 at 18:50














              5












              5








              5







              In sed you can use a range (stopping on the empty line at the end of the [shovel] category):



              sed '/[shovel]/,/^$/ s/enabled = 0/enabled = 1/' file


              the first part /[shovel]/,/^$/ means find a line with [shovel], keep going until you find an empty line, and do the following command(s) (in this case a simple s/old/new) only on that part of file



              Note in response to comment: sed will not accept alternative delimiters in ranges and addresses (so escape any / characters that must be literal, if you need to match them), unless they are preceded by a backslash. You can always use an alternative delimiter in any following commands, for example:



              sed '/[shovel]/,/^$/ s|enabled = 0|enabled = 1|' file


              Or



              sed '|[shovel]|, |^$| s|enabled = 0|enabled = 1|' file





              share|improve this answer















              In sed you can use a range (stopping on the empty line at the end of the [shovel] category):



              sed '/[shovel]/,/^$/ s/enabled = 0/enabled = 1/' file


              the first part /[shovel]/,/^$/ means find a line with [shovel], keep going until you find an empty line, and do the following command(s) (in this case a simple s/old/new) only on that part of file



              Note in response to comment: sed will not accept alternative delimiters in ranges and addresses (so escape any / characters that must be literal, if you need to match them), unless they are preceded by a backslash. You can always use an alternative delimiter in any following commands, for example:



              sed '/[shovel]/,/^$/ s|enabled = 0|enabled = 1|' file


              Or



              sed '|[shovel]|, |^$| s|enabled = 0|enabled = 1|' file






              share|improve this answer














              share|improve this answer



              share|improve this answer








              edited Feb 15 at 18:51

























              answered Jan 27 '17 at 5:45









              ZannaZanna

              2,6161023




              2,6161023













              • Perfect. How would I change the delimiter? One of the values is a pathname so I'm trying to change the delimiter to a pipe. I've tried replacing all of the delimiters as well as just the two following the 's' and both error out. -sed -i "/[shovel]/,/^$/ s|home = .*|home = /home/test/" file gives me: sed: -e expression #1, char 48: unterminated 's' command and -sed -i "|[shovel]|,|^$| s|home = .*|home = /home/test/" file gives me: sed: -e expression #1, char 1: unknown command: '|'

                – user1930831
                Jan 27 '17 at 17:01













              • You just need to put the last delimiter in: sed '/[shovel]/,/^$/ s|enabled = 0|enabled = 1|' @user1930831 :)

                – Zanna
                Jan 27 '17 at 18:50



















              • Perfect. How would I change the delimiter? One of the values is a pathname so I'm trying to change the delimiter to a pipe. I've tried replacing all of the delimiters as well as just the two following the 's' and both error out. -sed -i "/[shovel]/,/^$/ s|home = .*|home = /home/test/" file gives me: sed: -e expression #1, char 48: unterminated 's' command and -sed -i "|[shovel]|,|^$| s|home = .*|home = /home/test/" file gives me: sed: -e expression #1, char 1: unknown command: '|'

                – user1930831
                Jan 27 '17 at 17:01













              • You just need to put the last delimiter in: sed '/[shovel]/,/^$/ s|enabled = 0|enabled = 1|' @user1930831 :)

                – Zanna
                Jan 27 '17 at 18:50

















              Perfect. How would I change the delimiter? One of the values is a pathname so I'm trying to change the delimiter to a pipe. I've tried replacing all of the delimiters as well as just the two following the 's' and both error out. -sed -i "/[shovel]/,/^$/ s|home = .*|home = /home/test/" file gives me: sed: -e expression #1, char 48: unterminated 's' command and -sed -i "|[shovel]|,|^$| s|home = .*|home = /home/test/" file gives me: sed: -e expression #1, char 1: unknown command: '|'

              – user1930831
              Jan 27 '17 at 17:01







              Perfect. How would I change the delimiter? One of the values is a pathname so I'm trying to change the delimiter to a pipe. I've tried replacing all of the delimiters as well as just the two following the 's' and both error out. -sed -i "/[shovel]/,/^$/ s|home = .*|home = /home/test/" file gives me: sed: -e expression #1, char 48: unterminated 's' command and -sed -i "|[shovel]|,|^$| s|home = .*|home = /home/test/" file gives me: sed: -e expression #1, char 1: unknown command: '|'

              – user1930831
              Jan 27 '17 at 17:01















              You just need to put the last delimiter in: sed '/[shovel]/,/^$/ s|enabled = 0|enabled = 1|' @user1930831 :)

              – Zanna
              Jan 27 '17 at 18:50





              You just need to put the last delimiter in: sed '/[shovel]/,/^$/ s|enabled = 0|enabled = 1|' @user1930831 :)

              – Zanna
              Jan 27 '17 at 18:50













              0














              Here's a solution using Perl, assuming your configuration is in config.ini:



              perl -000 -n -i -e 's/^enabled = 0$/enabled = 1/m if /^[shovel]n/; print;' config.ini


              This does the following:





              • -000 - Read file in paragraph mode, essentially the same as doing $/ = "nn"; in the code.


              • -n - Run the specified code inside a while (<>) { } loop.


              • -i - In-line edit the specified file instead of printing to standard output. You can optionally specify an extension, which will cause the input file to be backed up with that extension. For instance, -i.bak would create a backup file called config.ini.bak.


              • -e - Executes the specified perl code.


              The code itself says to replace lines containing exactly enabled = 0 with enabled = 1 if the input "paragraph" starts with [shovel] on a line by itself. The [ and ] have to be escaped since they normally have special meaning in a regular expression.






              share|improve this answer
























              • If you're using Perl, you could pick up the Config::IniFiles module and use that.

                – Kusalananda
                Jan 27 '17 at 8:01
















              0














              Here's a solution using Perl, assuming your configuration is in config.ini:



              perl -000 -n -i -e 's/^enabled = 0$/enabled = 1/m if /^[shovel]n/; print;' config.ini


              This does the following:





              • -000 - Read file in paragraph mode, essentially the same as doing $/ = "nn"; in the code.


              • -n - Run the specified code inside a while (<>) { } loop.


              • -i - In-line edit the specified file instead of printing to standard output. You can optionally specify an extension, which will cause the input file to be backed up with that extension. For instance, -i.bak would create a backup file called config.ini.bak.


              • -e - Executes the specified perl code.


              The code itself says to replace lines containing exactly enabled = 0 with enabled = 1 if the input "paragraph" starts with [shovel] on a line by itself. The [ and ] have to be escaped since they normally have special meaning in a regular expression.






              share|improve this answer
























              • If you're using Perl, you could pick up the Config::IniFiles module and use that.

                – Kusalananda
                Jan 27 '17 at 8:01














              0












              0








              0







              Here's a solution using Perl, assuming your configuration is in config.ini:



              perl -000 -n -i -e 's/^enabled = 0$/enabled = 1/m if /^[shovel]n/; print;' config.ini


              This does the following:





              • -000 - Read file in paragraph mode, essentially the same as doing $/ = "nn"; in the code.


              • -n - Run the specified code inside a while (<>) { } loop.


              • -i - In-line edit the specified file instead of printing to standard output. You can optionally specify an extension, which will cause the input file to be backed up with that extension. For instance, -i.bak would create a backup file called config.ini.bak.


              • -e - Executes the specified perl code.


              The code itself says to replace lines containing exactly enabled = 0 with enabled = 1 if the input "paragraph" starts with [shovel] on a line by itself. The [ and ] have to be escaped since they normally have special meaning in a regular expression.






              share|improve this answer













              Here's a solution using Perl, assuming your configuration is in config.ini:



              perl -000 -n -i -e 's/^enabled = 0$/enabled = 1/m if /^[shovel]n/; print;' config.ini


              This does the following:





              • -000 - Read file in paragraph mode, essentially the same as doing $/ = "nn"; in the code.


              • -n - Run the specified code inside a while (<>) { } loop.


              • -i - In-line edit the specified file instead of printing to standard output. You can optionally specify an extension, which will cause the input file to be backed up with that extension. For instance, -i.bak would create a backup file called config.ini.bak.


              • -e - Executes the specified perl code.


              The code itself says to replace lines containing exactly enabled = 0 with enabled = 1 if the input "paragraph" starts with [shovel] on a line by itself. The [ and ] have to be escaped since they normally have special meaning in a regular expression.







              share|improve this answer












              share|improve this answer



              share|improve this answer










              answered Jan 27 '17 at 5:48









              James SneeringerJames Sneeringer

              1,748911




              1,748911













              • If you're using Perl, you could pick up the Config::IniFiles module and use that.

                – Kusalananda
                Jan 27 '17 at 8:01



















              • If you're using Perl, you could pick up the Config::IniFiles module and use that.

                – Kusalananda
                Jan 27 '17 at 8:01

















              If you're using Perl, you could pick up the Config::IniFiles module and use that.

              – Kusalananda
              Jan 27 '17 at 8:01





              If you're using Perl, you could pick up the Config::IniFiles module and use that.

              – Kusalananda
              Jan 27 '17 at 8:01











              0














              can you try this awk solution



              awk '/shovel/{flag=1}flag&&/enabled/{$NF=1;flag=0}1' input





              share|improve this answer




























                0














                can you try this awk solution



                awk '/shovel/{flag=1}flag&&/enabled/{$NF=1;flag=0}1' input





                share|improve this answer


























                  0












                  0








                  0







                  can you try this awk solution



                  awk '/shovel/{flag=1}flag&&/enabled/{$NF=1;flag=0}1' input





                  share|improve this answer













                  can you try this awk solution



                  awk '/shovel/{flag=1}flag&&/enabled/{$NF=1;flag=0}1' input






                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Jan 27 '17 at 6:13









                  KamarajKamaraj

                  2,9741513




                  2,9741513























                      0














                      You can restrict sed to only modifying a particular line:



                       sed -i '3s/enabled = 0/enabled = 1/g' file


                      This will only modify the 3rd line for [purple]






                      share|improve this answer




























                        0














                        You can restrict sed to only modifying a particular line:



                         sed -i '3s/enabled = 0/enabled = 1/g' file


                        This will only modify the 3rd line for [purple]






                        share|improve this answer


























                          0












                          0








                          0







                          You can restrict sed to only modifying a particular line:



                           sed -i '3s/enabled = 0/enabled = 1/g' file


                          This will only modify the 3rd line for [purple]






                          share|improve this answer













                          You can restrict sed to only modifying a particular line:



                           sed -i '3s/enabled = 0/enabled = 1/g' file


                          This will only modify the 3rd line for [purple]







                          share|improve this answer












                          share|improve this answer



                          share|improve this answer










                          answered Jan 27 '17 at 7:17









                          Tom KellyTom Kelly

                          36726




                          36726






























                              draft saved

                              draft discarded




















































                              Thanks for contributing an answer to Unix & Linux Stack Exchange!


                              • Please be sure to answer the question. Provide details and share your research!

                              But avoid



                              • Asking for help, clarification, or responding to other answers.

                              • Making statements based on opinion; back them up with references or personal experience.


                              To learn more, see our tips on writing great answers.




                              draft saved


                              draft discarded














                              StackExchange.ready(
                              function () {
                              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f340459%2fmatch-a-pattern-and-replace-the-first-instance-of-string-following-it%23new-answer', 'question_page');
                              }
                              );

                              Post as a guest















                              Required, but never shown





















































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown

































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown







                              Popular posts from this blog

                              How to reconfigure Docker Trusted Registry 2.x.x to use CEPH FS mount instead of NFS and other traditional...

                              is 'sed' thread safe

                              How to make a Squid Proxy server?