re.match matches at the beginning of the input string.
To match anywhere, use re.search instead.
>>> import re
>>> re.match('a', 'abc')
<_sre.SRE_Match object at 0x0000000001E18578>
>>> re.match('a', 'bac')
>>> re.search('a', 'bac')
<_sre.SRE_Match object at 0x0000000002654370>
See search() vs. match():
Answer from falsetru on Stack OverflowPython offers two different primitive operations based on regular expressions: re.match() checks for a match only at the beginning of the string, while re.search() checks for a match anywhere in the string (this is what Perl does by default).
re.match matches at the beginning of the input string.
To match anywhere, use re.search instead.
>>> import re
>>> re.match('a', 'abc')
<_sre.SRE_Match object at 0x0000000001E18578>
>>> re.match('a', 'bac')
>>> re.search('a', 'bac')
<_sre.SRE_Match object at 0x0000000002654370>
See search() vs. match():
Python offers two different primitive operations based on regular expressions: re.match() checks for a match only at the beginning of the string, while re.search() checks for a match anywhere in the string (this is what Perl does by default).
.match() constrains the search to begin at the first character of the string. Use .search() instead. Note too that . matches any character (except a newline). If you want to match a literal period, escape it (\. instead of plain .).
Exact Word Match in String with Regex in Python - Post.Byes
Regex exact match search
How to match exact word with regex python? - Stack Overflow
python - How to match an exact word inside a string? - Stack Overflow
I suggest bookmarking the MSDN Regular Expression Quick Reference
you want to achieve a case insensitive match for the word "rocket" surrounded by non-alphanumeric characters. A regex that would work would be:
\W*((?i)rocket(?-i))\W*
What it will do is look for zero or more (*) non-alphanumeric (\W) characters, followed by a case insensitive version of rocket ( (?i)rocket(?-i) ), followed again by zero or more (*) non-alphanumeric characters (\W). The extra parentheses around the rocket-matching term assigns the match to a separate group. The word rocket will thus be in match group 1.
UPDATE 1:
Matt said in the comment that this regex is to be used in python. Python has a slightly different syntax. To achieve the same result in python, use this regex and pass the re.IGNORECASE option to the compile or match function.
\W*(rocket)\W*
On Regex101 this can be simulated by entering "i" in the textbox next to the regex input.
UPDATE 2 Ismael has mentioned, that the regex is not quite correct, as it might match "1rocket1". He posted a much better solution, namely
(?:^|\W)rocket(?:$|\W)
I think the look-aheads are overkill in this case, and you would be better off using word boundaries with the ignorecase option,
\brocket\b
In other words, in python:
>>> x="rocket's"
>>> y="rocket1."
>>> c=re.compile(r"\brocket\b",re.I) # with the ignorecase option
>>> c.findall(y)
[]
>>> c.findall(x)
['rocket']
I'm searching for exact word match of the word - "new"
in the string - "This is a new String"
using the regex - /^new$/
But the regex101 does not match anything, what am i missing ?
https://regex101.com/r/o1TBGn/1
You can use a negative lookbehind and a negative lookahead pattern to ensure that each matching keyword is neither preceded nor followed by a non-space character:
(?<!\S)(?:c|java)(?!\S)
Demo: https://regex101.com/r/GOF8Uo/3
Alternatively, simply split the given string into a list of words and test if any word is in the set of keywords you're looking for:
def match(x):
return any(w in {'c', 'java'} for w in x.split())
Have you tried using one of the regex test sites such as this one or this one?? They will analyse your regex patterns and explain exactly what you are actually trying to match. There are many others.
I am not familiar with the python match function, but it appears that it parses your input pattern into
\bc\b|\bjava\b
which matches either 'c' or 'java' at a word boundary. Consequently it will find a 'c' at both ends of "0", the beginning of "1" and "2", return "no match" for "3" and match 'java' in "4" which accounts for your results.
You can require that there should not be a non-whitespace symbol on both sides of the word:
r'(?<!\S){0}(?!\S)'.format(re.escape(word))
See the regex demo
I added re.escape(word) in case your keywords contain special regex metacharacters that should be treated literally.
See Python demo:
import re
word = "8"
pat = r'(?<!\S){0}(?!\S)'.format(re.escape(word))
print re.search(pat,"nnn 8", flags=re.IGNORECASE)
Word boundaries won't help because - is not considered a word character.
You can use lookarounds:
p = re.compile(r'(?:(?<=^)|(?<=\s))' + word + r'(?=\s|$)', flags=re.IGNORECASE|re.M)
re.search(p, op1)
Code Demo
(?<=^)|(?<=\s)is a lookbehind to ensure we have line start or whitespace before our word(?=\s|$)is a lookahead to ensure we have line end or whitespace next to our word
You may consider the following approaches.
TLS as a whole word should have a word boundary right in front of it, so that part is covered in your pattern.
If there must be a whitespace right after 1, or end of string, it is more efficient to use a negative lookahead (?!\S): r'\bTLS 1(?!\S)'. Well, you may also use r'\bTLS 1(?:\s|$)'. See this regex demo.
If you just want to ensure there is no digit or a fractional part after 1 use
r'\bTLS 1(?!\.?\d)'
This will match TLS 1 that has no . or . + digit after it. See this regex demo.
Python demo:
import re
target = ['TLS 1.2 x67 DHE-RSA-AES128-SHA256 DH 2048 AES128 TLS_DHE_RSA_WITH_AES_128_CBC_SHA256', 'TLS 1 x67 DHE-RSA-AES128-SHA256 DH 2048 AES128 TLS_DHE_RSA_WITH_AES_128_CBC_SHA256',
'TLS 1.1 x67 DHE-RSA-AES128-SHA256 DH 2048 AES128 TLS_DHE_RSA_WITH_AES_128_CBC_SHA256']
lines=[]
for i in target:
if re.match(r'\bTLS 1(?!\.?\d)', i):
lines.append(i)
print(lines)
Output:
['TLS 1 x67 DHE-RSA-AES128-SHA256 DH 2048 AES128 TLS_DHE_RSA_WITH_AES_128_CBC_SHA256']
Wiktor commented before I posted this (not surprising), but the marker for an exact match in this case is actually a space following TLS 1. A word boundary is not specific enough, because that would also pick up things like TLS 1.1, which you don't want. So try this version:
#returns all the lines including TLS 1.1, TLS 1.2 ...
lines = []
for i in target:
if re.match(r'\bTLS 1\s', i):
lines.append(i)
If the TLS text could possibly be the very last thing in a line, then we can try using this:
re.match(r'\bTLS 1(?=(\s|$))', i)
Make your own word-boundary:
def exact_Match(phrase, word):
b = r'(\s|^|$)'
res = re.match(b + word + b, phrase, flags=re.IGNORECASE)
return bool(res)
copy-paste from here to my interpreter:
>>> str1 = "award-winning blueberries"
>>> word1 = "award"
>>> word2 = "award-winning"
>>> exact_Match(str1, word1)
False
>>> exact_Match(str1, word2)
True
Actually, the casting to bool is unnecessary and not helping at all. The function is better off without it:
def exact_Match(phrase, word):
b = r'(\s|^|$)'
return re.match(b + word + b, phrase, flags=re.IGNORECASE)
note: exact_Match is pretty unconventional casing. just call it exact_match.
The problem with your initial method is that '\\b' does not denote the zero-width assertion search that your looking for. (And if it did, I would use r'\b' instead because backslashes can become a real hassle in regular expressions - see this link)
From Regular Expression HOWTO
\b
Word boundary. This is a zero-width assertion that matches only at the beginning or end of a word. A word is defined as a sequence of alphanumeric characters, so the end of a word is indicated by whitespace or a non-alphanumeric character.
Because - is a non-alphanumeric character, your findall regular expression will find award in award-wining but not in awards.
Depending on your searched phrase, I would also think of using re.findall instead of re.match as suggested by Elazar. In your example re.match works, but if the word you are looking for is nested anywhere beyond the beginning of the string, re.match will not succeed.
For this kind of thing, regexps are very useful :
import re
print(re.findall('\\blocal\\b', "Hello, locally local test local."))
// ['local', 'local']
\b means word boundary, basically. Can be space, punctuation, etc.
Edit for comment :
print(re.sub('\\blocal\\b', '*****', "Hello, LOCAL locally local test local.", flags=re.IGNORECASE))
// Hello, ***** locally ***** test *****.
You can remove flags=re.IGNORECASE if you don't want to ignore the case, obviously.
Below you can use simple function.
def find_word(text, search):
result = re.findall('\\b'+search+'\\b', text, flags=re.IGNORECASE)
if len(result)>0:
return True
else:
return False
Using:
text = "Hello, LOCAL locally local test local."
search = "local"
if find_word(text, search):
print "i Got it..."
else:
print ":("
You should use re.search here not re.match.
From the docs on re.match:
If you want to locate a match anywhere in string, use search() instead.
If you're looking for the exact word 'Not Ok' then use \b word boundaries, otherwise
if you're only looking for a substring 'Not Ok' then use simple : if 'Not Ok' in string.
>>> strs = 'Test result 1: Not Ok -31.08'
>>> re.search(r'\bNot Ok\b',strs).group(0)
'Not Ok'
>>> match = re.search(r'\bNot Ok\b',strs)
>>> if match:
... print "Found"
... else:
... print "Not Found"
...
Found
You could simply use,
if <keyword> in str:
print('Found keyword')
Example:
if 'Not Ok' in input_string:
print('Found string')
Try with specifying the start and end rules in your regex:
re.compile(r'^test-\d+$')
Since Python 3.4 you can use re.fullmatch to avoid adding ^ and $ to your pattern.
>>> import re
>>> p = re.compile(r'\d{3}')
>>> bool(p.match('1234'))
True
>>> bool(p.fullmatch('1234'))
False