Reputation: 59
I want to match a line that contains a word, but does not have semi-colon in it
This should match:
class test
this should not match
class test;
this should not match either
class test; // test class
this is what I was expecting to work, but it doesn't:
pattern="class [^;]*"
if [[ $line =~ $pattern ]]
thanks
Upvotes: 5
Views: 2988
Reputation: 45686
Your regular expression is not anchored which means that [^;]*
will still match against all characters up to a possible ;
(and thus match as a whole). If you anchor the regex against the end of the line ([^;]*$
) it will produce the results you are after:
$ cat t.sh
#!/bin/bash
pattern='class [^;]*$'
while read -r line; do
printf "testing '${line}': "
[[ $line =~ $pattern ]] && echo matches || echo "doesn't match"
done <<EOT
class test
class test;
class test; // test class
EOT
$ ./t.sh
testing 'class test': matches
testing 'class test;': doesn't match
testing 'class test; // test class': doesn't match
TL;DR: In other words, the bold part in
class test; foo bar quux
matches your regex even though the string contains a semicolon which is why it always matches. The anchor makes sure that the regular expression only matches if there is no semicolon until the very end of the string.
Upvotes: 3
Reputation: 195229
how about straightforwardly:
pattern="^[^;]*\bclass\b[^;]*$"
\b
word boundary was added, for matching xxx class xxx
only, not matching superclass xxx
Upvotes: 1
Reputation: 15279
I think you need:
pattern="^[^;]*class [^;]*$"`
This ensures the line don't have a ; before or after your [^;]*
match.
Upvotes: 0
Reputation: 191809
Use ^[^;]+($|\s*//)
. This means any number of non-semicolon characters (at least one) from the start of the string until either the end of the line or any number of spaces followed by two slashes.
http://rubular.com/r/HTizIXz2HA
Upvotes: 0