11

The following checks if it begins with "End":

if [[ "$line" =~ ^End ]]

I am trying to find out how to match something that does not begin with "02/18/13". I have tried the following:

if [[ "$line" != ^02/18/13 ]]

if [[ "$line" != ^02\/18\/13 ]]

Neither of them seemed to work.

Benjamin W.
  • 46,058
  • 19
  • 106
  • 116
dalawh
  • 886
  • 8
  • 15
  • 37

3 Answers3

23

bash doesn't have a "doesn't match regex" operator; you can either negate (!) a test of the "does match regex" operator (=~):

if [[ ! "$line" =~ ^02/18/13 ]]

or use the "doesn't match string/glob pattern" operator (!=):

if [[ "$line" != 02/18/13* ]]

Glob patterns are just different enough from regular expressions to be confusing. In this case, the pattern is simple enough that the only difference is that globs are expected to match the entire string, and hence don't need to be anchored (in fact, it needs a wildcard to de-anchor the end of the pattern).

Gordon Davisson
  • 118,432
  • 16
  • 123
  • 151
  • Is there a difference from your negate inside the double brackets and gillyspy's negate outside of the double brackets? – dalawh May 16 '13 at 15:37
  • They're technically different, but will give the exact same result. Mine does the negation as part of the bash test expression, while gillspy's negates the result of the expression. If the expression were more complex it might matter (e.g. if the expression had several tests and-ed or or-ed together, negating inside would negate only part of the expression, while negating outside would negate the entire thing -- though actually, you can get either result either way if you use parentheses and brackets properly). – Gordon Davisson May 16 '13 at 16:25
  • So lets say I have a test expression like this: if [[ exp1 && exp2 ]]. In this case, the "!" will matter? If it is outside the brackets, it means not both exp1 and exp2, but if it is inside, it is not one or the other depending where it is placed (either in front of exp1 or exp2), right? – dalawh May 16 '13 at 16:49
  • Correct. `[[ ! exp1 && exp2 ]]` returns true if exp1 is false and exp2 is true, while `! [[ exp1 && exp2 ]]` returns true if either exp1 or exp2 is false. Note that `! [[ exp1 && exp2 ]]` is equivalent to `[[ ! ( exp1 && exp2 ) ]]` which is equivalent (via [De Morgan's law](http://en.wikipedia.org/wiki/De_Morgan%27s_laws)) to `[[ ! exp1 || ! exp2 ]]`, which is equivalent to `! [[ exp1 ]] || ! [[ exp2 ]]`. There are many ways to compute the same result... – Gordon Davisson May 16 '13 at 17:13
5

Why not just "if not" it?

if ! [[ "$line" =~ ^02/18/13 ]]
gillyspy
  • 1,578
  • 8
  • 14
  • 1
    Is there a difference from Gordon Davisson's negate inside the double brackets and your negate outside of the double brackets? – dalawh May 16 '13 at 15:37
1

Using the if ! will do the trick. Example: Say line="1234" using this test in bash -

if ! echo "$line" |grep -q "^:" > /dev/null; then echo "GOOD line does NOT begin with : "; else echo "BAD - line DOES begin with : "; fi

It will respond with "GOOD line does NOT begin with : "

Kyle L
  • 11
  • 1