18

In a file containing lines like this one:

# lorem ipsum blah variable

I would like to remove # (comment) character in the same line that contains a specific string, in place. Is sed good for this?

I'm struggling to get this conditional working. I have a "clumsy" way of doing this; I can find the matching line number with awk or sed and then use this number in a separate sed command, but I believe that this can be done in a much better way.

31

Use the string you are looking for as the selector for the lines to be operated upon:

sed '/ipsum/s/#//g'

/ipsum/ selects lines containing "ipsum" and only on these lines the command(s) that follow are executed. You can use braces to run more commands

/ipsum/{s/#//g;s/@/-at-/g;}
  • 4
    I agree; this is the best answer (although not the only one). Comments: (1) 's/#//g' will remove all the # characters in the line. If that’s not what you want, remove the g (which stands for “global”). (2) To edit a file in place (as asked for in the question), use sed -i. – G-Man Sep 12 '14 at 21:54
  • 2
    (3) As a matter of real-world situations, if you want to un-comment a line, you might want to use sed -i '/ipsum/s/#[[:space:]]*//', to get rid of any spaces and tabs immediately following the #. (4) You might also want to consider verifying that the # is the first non-blank character in the line. The current command would delete the # from the line prompt "Enter # of ipsums:". – G-Man Sep 12 '14 at 21:55
  • 1
    @G-Man - great addition! To your 2nd pt (leading space), what about: sed -i '/ipsum/s/^#[[:space:]]*//'?! (^ signifies start of line, $ for end of line) - at least in gnu sed... – Jeremy Davis Oct 19 '17 at 6:02
  • 1
    @JeremyDavis: Yes, you could anchor the regex to the beginning of the line with ^, but that would be wrong. I often comment out indented code by putting the # immediately before the code, so the # is indented.  I doubt that I’m the only person who does that. – G-Man Oct 21 '17 at 3:50
  • 1
    @G-Man - ah yes, of course! Thanks, I hadn't considered that. So you'd also want to check for whitespace between ^ & #, so something more like this: /ipsum/{/^[[:space:]]*#/s/#[[:space:]]*//}. Although even then, depending on where the # is, it may still cause issues (e.g. in languages that use whitespace indentation/separation). – Jeremy Davis Oct 22 '17 at 0:04
7
$ cat input.txt
# lorem ipsum blah variable
# lorem ipsum blat variable
# lorem ipsum blow variable
# lorem ipsum blip variable
# lorem ipsum blue variable

then:

$ sed 's|# \(.*blue.*\)|\1|' input.txt

gives:

# lorem ipsum blah variable
# lorem ipsum blat variable
# lorem ipsum blow variable
# lorem ipsum blip variable
lorem ipsum blue variable

It works as follows:

The s tells sed that it should substitute what the regular expression finds.

The pattern is # \(.*blue.*\) which breaks down to: Find a hash followed by a space. The bracket (\() starts the grouping. .*blue.* is the word blue with anything before and after. The next bracket (\)) closes the grouping.

The replacement is \1 which is a back-reference to the content of the first grouping bracket.

3

You can use Vim in Ex mode:

ex -sc '/ipsum/s/#//|x' file
  1. s substitute

  2. x save and close

  • That's pretty cool. I didn't know about that! TBH, I'm not sure it's the best answer for this question (IMO the leading sed answer is the one) but it's still very cool! Thanks for posting. – Jeremy Davis Oct 19 '17 at 5:55

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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