2

Using sed, how do I search for a line ending with foo and then edit the next line if it starts with #bar?

Or put another way, I want to remove a comment # from the next line if it starts with #bar and the previous line ends in foo.

For example:

This is a line ending in foo
#bar is commented out
There are many lines ending in foo
#bar commented out again

I tried:

sed -i 's/^foo\n#bar/foo\nbar/' infile
3

Use the N;P;D cycle and attempt to substitute each time:

sed '$!N;s/\(foo\n\)#\(bar\)/\1\2/;P;D' infile

this removes the leading # from #bar only if it follows a line ending in foo otherwise it just prints the pattern space unmodified.


Apparently, you want to uncomment US mirrors in /etc/pacman.d/mirrorlist which is a whole different thing:

sed -e '/United States/,/^$/{//!s/^#//' -e '}' /etc/pacman.d/mirrorlist

This will uncomment all mirrors in the US section in /etc/pacman.d/mirrorlist

  • This prints the lines, but it is not removing the '#'. It may be my implementation. I am using Arch Linux and am attempting to remove all the comments from the United States servers in the mirrorlist file. – CompSci-PVT May 24 '16 at 14:09
  • It does for me (archlinux too) so there's something wrong with your file. Maybe you have spaces, try with sed '$!N;s/\(foo[[:blank:]]*\n\)#\([[:blank:]]*bar\)/\1\2/;P;D' infile – don_crissti May 24 '16 at 14:11
  • I was looking at this website and I commented out all the servers, and then wanted to only uncomment United States servers: wiki.archlinux.org/index.php/Mirrors#Sorting_mirrors – CompSci-PVT May 24 '16 at 14:26
  • @CompSci-PVT - lol, that's a whole different question dude... You want to uncomment all commented lines that follow a pattern inside a paragraph. See my updated post though you should edit the question to reflect your actual requirements. – don_crissti May 24 '16 at 14:44
2
sed '/foo$/{n;s/^#bar/bar/;}'

is a literal translation of your requirement. n is for next.

Now that doesn't work in cases like:

line1 foo
#bar line2 foo
#bar

Or:

line1 foo
line2 foo
#bar

Which you could address by doing:

sed '
  :1
  /foo$/ {
     n
     s/^#bar/bar/
     b1
  }'
  • Is there any reason you didn't use P;D for one line only solution? – cuonglm May 24 '16 at 15:09
  • 1
    @cuonglm, it looks like the P;D approaches are already covered in other answers. This answer shows the direct translation of the requirement approach (search for foo$, get the next line, substitute) along with its limitations. – Stéphane Chazelas May 24 '16 at 15:17
1

Try:

sed -e '$!N;/foo\n#bar/s/\(\n\)#/\1/;P;D'
  • Using this, I get an error: sed: -e expression #1, char 35: unknown option to 's' – CompSci-PVT May 24 '16 at 14:00
  • @CompSci-PVT: Missing the ;, updated. – cuonglm May 24 '16 at 14:05
  • I am sure your answer is supposed to work, but it is not removing the '#' on my machine. Same as above answer. I will have to investigate more. – CompSci-PVT May 24 '16 at 14:10
  • @CompSci-PVT: Check you line ends with foo or foo with trailing spaces? – cuonglm May 24 '16 at 14:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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