I have a file with entries like this:

chr1    740678  740720
chr1    2917480 2917507

I want to remove the entries which start with chr1 but retain others which start with chr11 or chr19 and so on. When I use grep -v "chr1" it removes the others which start with chr11 or chr19. Can I use another regular expression?


First, you should anchor your regular expression to only match at the beginning of the line (^chr1) to avoid finding lines that contain chr1 but it isn't the first string (this can easily happen with an annotated VCF file, for example). Next, you can use the -w option for (GNU) grep:

   -w, --word-regexp
          Select  only  those  lines  containing matches that
          form whole words.  The test is  that  the  matching
          substring  must  either  be at the beginning of the
          line,  or  preceded  by  a   non-word   constituent
          character.  Similarly, it must be either at the end
          of the line or followed by a  non-word  constituent
          character.     Word-constituent    characters   are
          letters, digits, and the underscore.   This  option
          has no effect if -x is also specified.

If your grep doesn't support that, then use this:

grep -v '^chr1\s' file

The \s matches whitespace (including both tabs and spaces), so that will exclude any lines that start with chr1 and then any kind of whitespace character.

| improve this answer | |
  • 1
    I wonder if \b (word boundary) would work in this context - and might be more portable than \s? – steeldriver Aug 5 at 11:27
  • 1
    @steeldriver hmm, yes (by the way, wouldn't \> be more portable? I thought \b was an ERE or even PCRE thing) but that would also exclude things like chr1|chr2, for example, which might be a problem for the OP. – terdon Aug 5 at 13:00
  • I get so confused! I thought that \b was the POSIX one and that \> and \< were GNU-specific. Also that \s is really from PCRE (although apparently supported by GNU grep in both ERE and BRE mode) – steeldriver Aug 5 at 15:10
  • 1
    @steeldriver ugh, I don't know either. I admit I tend to stick to PCRE whenever remotely possible and never remember the details for this sort of edge case. According to this you're absolutely right and \> and \< are GNU extensions. However, according to that, so is \b so go figure :). And yes, I only found out that GNU grep supports \s when I read nobody's answer. I'd always assumed it didn't since the \s is a PCRE thing and just used grep -P. – terdon Aug 5 at 16:35
  • If your looking for portability maybe [[:space:]]? – Matt Aug 5 at 20:43

It looks like there are some spaces or tabs after chr1. So you could search for chr1, which is followed by some whitespace characters. Try this:

grep -v "chr1\s\+"
| improve this answer | |
  • 1
    The \+ could be unnecessary. – pasaba por aqui Aug 5 at 22:37
  • @pasaba por aqui: You are right. – nobody Aug 6 at 6:02

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.