-2

I've been using RegEx expressions in Python for a while and I want to find out if it possible to ask RegEx to match a line that has a value in the line but also does not have a value in the same line:

Given a line saying: filename.txt opt1 opt2 opt4

I want to say find filename.txt that does not have option3.

I used: ^(?!.*opt3).* filename.txt.*

I don't like how this reads BUT seams the only technique that might work

Keith
  • 4,129
  • 3
  • 13
  • 25
  • This will give you a problem if `filename` includes `opt3` – Nick Nov 13 '19 at 02:33
  • This didn't work for me. re.search( 'FileName.abc 0 opt1 opt2 opt4', '^(?!.*opt3)FileName\.abc' ) != None – Keith Nov 13 '19 at 03:36
  • This didn't work either. re.search( 'FileName.abc 0 opt1 opt2 opt4', '^(?!.*opt3).*(filename\.abc)' ) != None – Keith Nov 13 '19 at 03:39

3 Answers3

1

Maybe,

^(?!.*opt3)filename\.txt

might simply suffice.

Demo 1

Just in case, filename.txt wouldn't be at the beginning of the string, then

^(?!.*opt3).*(filename\.txt)

would be an option to look into, as well.

Demo 2

RegEx Circuit

jex.im visualizes regular expressions:

enter image description here

Test 1

import re

string = '''
filename.txt  opt1 opt2 opt4
filename.txt  opt1 opt2 opt3 opt4
 filename.txt  opt1 opt2 opt4
  filename.txt  opt1 opt2 opt3 opt4
'''

expression = r'^(?!.*opt3).*(filename\.txt)'

print(re.findall(expression, string, re.M))

Output 1

['filename.txt', 'filename.txt']

Test 2

If you wanted to swipe the entire string, you can simply add a .* at the end of the expression:

import re

string = '''
filename.txt  opt1 opt2 opt4
filename.txt  opt1 opt2 opt3 opt4
 filename.txt  opt1 opt2 opt4
  filename.txt  opt1 opt2 opt3 opt4
'''

expression = r'^(?!.*opt3).*filename\.txt.*'

print(re.findall(expression, string, re.M))

Output 2

['filename.txt  opt1 opt2 opt4', ' filename.txt  opt1 opt2 opt4']

Test 3

import re

string = '''
filename.txt  opt1 opt2 opt4
filename.txt  opt1 opt2 opt3 opt4
 filename.txt  opt1 opt2 opt4
  filename.txt  opt1 opt2 opt3 opt4
'''

expression = r'(?m)^(?!.*opt3).*filename\.txt.*'

print(re.findall(expression, string))

for item in re.finditer(expression, string):
    print(item.group(0))

Output

['filename.txt  opt1 opt2 opt4', ' filename.txt  opt1 opt2 opt4']
filename.txt  opt1 opt2 opt4
 filename.txt  opt1 opt2 opt4
Emma
  • 27,428
  • 11
  • 44
  • 69
  • interesting that re.findall() is finding it but it requires the 3rd parameter and the re.M. Otherwise it returns an empty list. re.search() won't find it at all. – Keith Nov 13 '19 at 03:44
1

In the code that you tried in the the comments, the first argument of re.search is the pattern and the second argument is the string.

Your code might look like

import re
match = re.search('^(?!.*opt3)FileName\.abc', 'FileName.abc 0 opt1 opt2 opt4')
if match:
    print(re.group())

See a Python demo

If the should not be opt3 in the string but opt3 can be part of a larger string, you could use lookarounds to make sure opt3 is not surrounded by non whitespace chars

^(?!.*(?<!\S)opt3(?!\S))filename\.txt
  • ^ Start of string
  • (?! Negative lookahead, assert what is on the right is not
    • .* Match any char except a newline 0+ times
    • (?<!\S)opt3(?!\S) match opt3 not surrounded by non whitespace chars
  • ) Close lookahead
  • filename\.txt match literally

Regex demo

The fourth bird
  • 154,723
  • 16
  • 55
  • 70
0

If you want a single regex, then your approach is how I would do this, but you should place word boundaries around the various terms:

^(?!.*\bopt3\b).*\bfilename.txt\b.*$

You could also do this using two separate calls to re.search, e.g.

line = "filename.txt  opt1 opt2 opt4"
if re.search(r'^.*\bfilename.txt\b.*$', line) and not re.search(r'^.*\bopt3\b.*$', line):
    print("line is a match")
Tim Biegeleisen
  • 502,043
  • 27
  • 286
  • 360