0

I am trying to grep all valid lines of a conf file that do not start with

  • a hash (or)
  • any number of spaces (0 or many) and a hash

The regexes below don't seem to work.

grep ^[^[[:blank:]]*#] /opt/logstash/logstash.conf

grep ^[^[[[:blank:]]*#]] /opt/logstash/logstash.conf

grep ^[^[\s]*#] /opt/logstash/logstash.conf

I'm trying to understand what am I doing wrong.

FWIW, the below regex works:

grep -v '^[[:blank:]]*#' /opt/logstash/logstash.conf
Benjamin W.
  • 46,058
  • 19
  • 106
  • 116
deppfx
  • 701
  • 1
  • 10
  • 24

1 Answers1

2

First of all, if you don't quote your regex, the shell might expand it before grep even sees it, so you should always quote your grep regexes.

Secondly, the reason why they don't work is this: [], the "bracket expression", matches any of the elements it contains, or their complement when using [^...]. You seem to try to match a negated sequence of characters, but that's not what [] does.

Also, within a bracket expression, character classes shouldn't be double bracketed: [^[:blank:]] instead of [^[[:blank:]]].

I'm not sure if it's possible without -v and just Basic or Extended Regular Expressions, but with a grep that can do Perl Regular Epxressions (such as GNU grep), you could use a negative look-ahead:

grep -P '^(?![[:blank:]]*#)' /opt/logstash/logstash.conf

Here is how your regexes fail (assuming they're quoted):

  • ^[^[[:blank:]]*#] – Matches any line that starts with zero or more characters other than a literal [ or a blank, followed by #]
  • ^[^[[[:blank:]]*#]] – Matches any line that starts with zero or more characters other than a literal [ or a blank (the repeated [[ within the bracket expression is the same as a single [), followed by #]]
  • ^[^[\s]*#] – Matches any line that starts with zero or more characters other than [, \ or s (\s is not special in []), followed by #].

If we take this test file:

# comment
normal line
    normal line after spaces
    # comment after spaces
    normal line after tab
    # comment after tab
abc#] does not start with blank or [ and has #]
[abc#] starts with [ and has #]
abc#]] does not start with blank or [ and has #]]
 abc#]] starts with blank and has #]]
sabc#]] starts with s and has #]]
\abc#]] starts with \ and has #]]

The expressions match as follows:

  • Your grep -v (works):

    $ grep -v '^[[:blank:]]*#' infile
    normal line
        normal line after spaces
        normal line after tab
    abc#] does not start with blank or [ and has #]
    [abc#] starts with [ and has #]
    abc#]] does not start with blank or [ and has #]]
     abc#]] starts with blank and has #]]
    sabc#]] starts with s and has #]]
    \abc#]] starts with \ and has #]]
    
  • My grep -P (works):

    $ grep -P '^(?![[:blank:]]*#)' infile
    normal line
        normal line after spaces
        normal line after tab
    abc#] does not start with blank or [ and has #]
    [abc#] starts with [ and has #]
    abc#]] does not start with blank or [ and has #]]
     abc#]] starts with blank and has #]]
    sabc#]] starts with s and has #]]
    \abc#]] starts with \ and has #]]
    
  • Your first try:

    $ grep '^[^[[:blank:]]*#]' infile
    abc#] does not start with blank or [ and has #]
    abc#]] does not start with blank or [ and has #]]
    sabc#]] starts with s and has #]]
    \abc#]] starts with \ and has #]]
    
  • Your second try:

    $ grep '^[^[[[:blank:]]*#]]' infile
    abc#]] does not start with blank or [ and has #]]
    sabc#]] starts with s and has #]]
    \abc#]] starts with \ and has #]]
    
  • Your third try:

    $ grep '^[^[\s]*#]' infile
    abc#] does not start with blank or [ and has #]
    abc#]] does not start with blank or [ and has #]]
     abc#]] starts with blank and has #]]
    
Benjamin W.
  • 46,058
  • 19
  • 106
  • 116