Filtering text that ends with certain char(all occurrences) in python through regexp

Viewed 57

I'm trying to filter text in python

import re
text = "Fast charging 25W, USB Power Delivery 3.0, Fast Qi/PMA wireless charging 12W, Reverse wireless charging 4.5W"
regex = re.compile("\w+\s\w+harg\w+\s\d+W")  
mc = regex.findall(text)
print(mc)

The result is

['Fast charging 25W', 'wireless charging 12W']

However, what I wanna do is get all occurrences end with *W"

['Fast charging 125W', 'Fast Qi/PMA wireless charging 12W', 'Reverse wireless charging 4.5W']

The number can be much larger(Like Charge 1250W) I googled almost 2 hours with lots of document about regexp but in vain. any help will be appreciated.

Thank you.

4 Answers

You are looking for a word boundary, and, if I understand correctly, everything between commas:

[^,]+?W\b
  • Everything that is not a comma, lazy
  • Literal uppercase W, followed by a word boundary \b

Online Demo, Code Sample:

import re
regex = r"[^,]+?W\b"
test_str = ("text = \"Fast charging 25W, USB Power Delivery 3.0, Fast Qi/PMA wireless charging 12W, Reverse wireless charging 4.5W\"\n")
matches = re.finditer(regex, test_str, re.MULTILINE)
for matchNum, match in enumerate(matches, start=1):  
    print ("Match {matchNum} was found at {start}-{end}: {match}".format(matchNum = matchNum, start = match.start(), end = match.end(), match = match.group()))

You can start the match with a word character, match charging between chars which are not a comma, and then match at least a digit before the W

(?<!\S)[^,]*\bcharg\w+\b[^,]*\dW\b

Explanation

  • (?<!\S) Assert whitespace boundary on the left
  • [^,]* Match 0+ occurrences of any char except ,
  • \bcharg\w+\b A word boundary, match charg followed by 1+ word chars and a word boundary
  • [^,]* Match 0+ occurrences of any char except ,
  • \dW\b Match at least a single digit followed by W and a word boundary

Regex demo

import re

s = "Fast charging 25W, USB Power Delivery 3.0, Fast Qi/PMA wireless charging 12W, Reverse wireless charging 4.5W, Charge 1250W"
print(re.findall(r"(?<!\S)[^,]*\bcharg\w+\b[^,]*\dW\b", s, re.IGNORECASE))

Output

[
    'Fast charging 25W',
    'Fast Qi/PMA wireless charging 12W',
    'Reverse wireless charging 4.5W',
    'Charge 1250W'
]

Or if there can only be digits in the part with the W, you can exclude matching the digits as well [^,\d] and optionally match a decimal part (?:\.\d+)?

(?<!\S)[^,]*\bcharg\w+\b[^,\d]*\d+(?:\.\d+)?W\b

Regex demo

This will capture all W with one or more digits in front of it

Code:

import re
text = "Fast charging 25W, USB Power Delivery 3.0, Fast Qi/PMA wireless charging 12W, Reverse wireless charging 4.5W"

pattern = '((\d[.])?\d+[W])'
matches = [match.group() for match in re.finditer(pattern, text)]
print(matches)

Output:

['25W', '12W', '4.5W']

Another solution using numpy using char.endswith.

import numpy as np

text = "Fast charging 25W, USB Power Delivery 3.0, Fast Qi/PMA wireless charging 12W, Reverse wireless charging 4.5W"
A = np.array(text.split(",")) 
v = np.char.endswith(A, 'W') 
A[v]

Output:

array(['Fast charging 25W', ' Fast Qi/PMA wireless charging 12W',
   ' Reverse wireless charging 4.5W'], dtype='<U34')
Related