2

I am trying to search for a specific item [7_addons] and ONLY replace the NEXT entry that appears from enabled=0 to enabled=1.

in this example:

sed -i -e 's#enabled=0#enabled=1#g' /etc/file.txt

..replaces EVERYTHING showing enabled=0 in file.txt, but I ONLY want it to replace what comes next after the search string 7_addons, replace =0 with =1, then STOP.

  • 4
    What does your data look like and what do you want it to look like after your modification? Update the question, don't add comments. – Kusalananda Jan 7 at 21:25
  • It is a file with repository info - after each repository definition, the last line in that section contains the line: enabled=0 So each repository section in the file has its own tag, in brackets ie.[ol7_addons] I was sed to search for the tag, then ONLY modify the next occurance of enabled=0 and change it to enabled=1. (Note, its easy to do enabled=0 for everything in the file, but I dont want everything enabled, just the next line that appears like that after the matcher) – Andrew J Jan 7 at 21:45
  • It is a file with repository info divided by sections - after each repository definition section, the last line in that section contains the line: enabled=0 Basically each repository section in the file has its own tag, in brackets ie.[ol7_addons] I wanted sed to search for the tag, then ONLY modify the next occurrence of enabled=0 and change it to enabled=1. (Note, its easy to do enabled=0 for everything in the file, but I dont want everything enabled, just the next line that appears like that after the matcher) – Andrew J Jan 7 at 21:51
  • 4
    Please update the question with a properly formatted example. – Kusalananda Jan 7 at 21:52
  • So what we need is a sample of maybe 10+ lines copied and pasted from your sample file into the question (exactly as they appear in the question). Also, type out an example of the output you'd like returned with relation to the example. – Crypteya Jan 7 at 22:37
2
sed '/\[7_addons\]/{n;s/enabled=0/enabled=1/}'

Or if there are other lines between [7_addons] and enabled=0:

sed '/\[7_addons\]/,/enabled=/s/enabled=0/enabled=1/'

Example:

$ cat foo
[2_foo]
enabled=0
[7_addons]
extra fluff
enabled=0
enabled=0
$ sed '/\[7_addons\]/,/enabled=/s/enabled=0/enabled=1/' foo
[2_foo]
enabled=0
[7_addons]
extra fluff
enabled=1
enabled=0

You may want to make the regexp a bit more strict; I cannot do that, based on the data from your question.

  • This would work if the enabled=0 was on the very next line after [7_addons], but not if it came later. This is why I asked the user to add a real example to the question. His description of the data is ambiguous. – Kusalananda Jan 7 at 22:09
  • If they add an example where this answer doesn't apply, I'll remove the answer (tomorrow morning). – mosvy Jan 7 at 22:12
  • Your 2nd solution won't work if there's anotherenabled= (e.g. enabled=1) line before the 1st enabled=0 that follows after the [7_addons] (which is highly unlikely I know...). Use a more strict range to take care of that: sed '/\[7_addons\]/,/enabled=0/s/enabled=0/enabled=1/' – don_crissti Jan 7 at 23:10
  • @don_crissti that was intended -- if [7_addons] is already followed by enabled=1, don't set to 1 an enabled=0 from from the next [section]. That would still wreak havoc if the [7_addons] section didn't have any enabled key whatsoever -- I'll assume that could not happen and leave it as is. – mosvy Jan 8 at 12:11
  • 1
    Yes, that's also true. Come to think, the best way to solve the problem here is to use a tool designed to process INI files. – don_crissti Jan 8 at 12:15
2

If you want to replace the assumed-exist enabled line that follows the first [7_addons] line in the file, you could use ed!

ed -s input <<< $'/^\[7_addons\]$\n/^enabled=0\nc\nenabled=1\n.\nw\nq' > /dev/null

Starting from the outside in, this executes ed in script mode on the input file and passes it an ANSI quoted string as a here-string, then redirects the output to /dev/null. The /dev/null redirection simply discards ed's reporting of the lines that it finds while doing the work.

The here-string breaks down to the following \n-separated commands:

  1. /^\[7_addons\]$ -- search forwards for the line that is exactly [7_addons] (being anchored to the beginning (^) and end ($) of the line
  2. /^enabled=0$ -- then search forwards for the line that is exactly enabled=0
  3. c -- change that line
  4. enabled=1 -- to this text
  5. . -- end the replacement text
  6. w -- write the file to disk
  7. q -- quit ed

On this sample input:

[1_addons]
enabled=0
foo=bar
[7_addons]
foo=baz
enabled=0
other=bat
[8_addons]
foo=quux

The resulting file is:

[1_addons]
enabled=0
foo=bar
[7_addons]
foo=baz
enabled=1
other=bat
[8_addons]
foo=quux

Not the answer you're looking for? Browse other questions tagged or ask your own question.