Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python regex search range of numbers

I couldn't seem to find a thread on this one, but it seems like something that should be pretty simple. I'm trying to use regex to search a line in an output for a number 0-99, and do one action, but if the number is 100 then it'll do a different action. Here's what I have tried(simplified version):

OUTPUT = #Some command that will store the output in variable OUTPUT
OUTPUT = OUTPUT.split('\n')
for line in OUTPUT:
    if (re.search(r"Rebuild status:  percentage_complete", line)): #searches for the line, regardless of number
        if (re.search("\d[0-99]", line)): #if any number between 0 and 99 is found
            print("error")
        if (re.search("100", line)): #if number 100 is found
            print("complete")

I've tried this and it still picks up the 100 and prints error.

like image 627
bladexeon Avatar asked Apr 14 '15 14:04

bladexeon


Video Answer


3 Answers

This: \d[0-99] means a digit (\d), followed by a number (0-9) or 9. If you are after the numeric range of [0-99], you would need to use something akin to \b\d{1,2}\b. This will match any numeric value which is made of 1 or 2 digits.

like image 144
npinti Avatar answered Oct 22 '22 05:10

npinti


You can simplify your regexes by re-ordering your number tests, and using elif instead of if on the test for 2 digit numbers.

for line in output:
    if re.search("Rebuild status:  percentage_complete", line): 
        if re.search("100", line):
            print "complete"
        elif re.search(r"\d{1,2}", line): 
            print "error"

The test for a 2 digit number is performed only if the test for "100" fails.

Using a raw string isn't strictly necessary with r"\d{1,2}" but it's a good habit to use a raw string for any regex that contains a backslash.

Note that you don't need parentheses around conditions in Python, so using them just adds unnecessary clutter.


As dawg mentions in the comments, the test for "100" can be tightened to re.search(r"\b100\b", line), but that's not needed if we can guarantee that we're only testing integer percentages in the range 0 - 100.

like image 31
PM 2Ring Avatar answered Oct 22 '22 03:10

PM 2Ring


0 - 99:

>>> s='\n'.join(["line {} text".format(i) for i in range(-2,101) ])
>>> import re
>>> re.findall(r'(?<!\-)\b(\d\d|\d)\b', s)
['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71', '72', '73', '74', '75', '76', '77', '78', '79', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '90', '91', '92', '93', '94', '95', '96', '97', '98', '99']

The regex '(?<!\-)\b(\d\d|\d)\b' matches 2 digits 0-99 and does not match negative numbers such as -9

Demo

100 is easy: '(?<!\-)\b100\b'

If you do not want to match floats: \b(?<![-.])(\d\d|\d)(?!\.)\b

Demo

like image 1
dawg Avatar answered Oct 22 '22 04:10

dawg