1

I'm doing something like "Syntax Analyzer" with Kivy, using re (regular expresions).

I only want to check a valid syntax for basic operations (like +|-|*|/|(|)). The user tape the string (with keyboard) and I validate it with regex. But I don't know how to use regex in an if statement. That I want is: If the string that user brings me isn't correct (or doesn't check with regex) print something like "inavlid string" and if is correct print "Valid string".

I've tried with:

if re.match(patron, string) is not None:
    print ("\nTrue")
else:
    print("False")

but, it doesn't matter what do string has, the app always show True.

Sorry my poor english. Any help would be greatly appreciated!

import  re

patron= re.compile(r"""

    (
    -?\d+[.\d+]?
    [+*-/]
    -?\d+[.\d+]?
    [+|-|*|/]?
    )*
    """, re.X)

obj1= self.ids['text'].text #TextInput
if re.match(patron, obj1) is not None:
    print ("\nValid String")
else:
    print("Inavlid string")

if obj1= "53.22+22.11+10*555+62+55.2-66" actually it's correct and app prints "Valid..." but if I put an a like this "a53.22+22.11+10*555+62+55.2-66" it's incorrect and the app must prints invalid.. but instead it still valid.

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
  • 1
    Possible duplicate of [Check if string matches pattern](https://stackoverflow.com/questions/12595051/check-if-string-matches-pattern) – dedObed Apr 04 '19 at 22:52
  • the kivy tag is irrelevant in this case, you are validating a string, and the kivy string is the native python string. – eyllanesc Apr 05 '19 at 04:41
  • Hi, and welcome to StackOverflow. Kudos for a well-written question that contains a [Minimal, Complete, and Verifiable example](http://stackoverflow.com/help/mcve). – Tim Pietzcker Apr 05 '19 at 05:18

2 Answers2

0

Your regex always matches because it allows the empty string to match (since the entire regex is enclosed in an optional group.

If you test this live on regex101.com, you can immediately see this and also that it doesn't match the entire string but only parts of it.

I've already corrected two errors in your character classes concerning the use of unnecessary/harmful alternation operators (|) and incorrect placement of the dash, making it into a range operator (-), but it's still incorrect.

I think you want something more like this:

^               # Make sure the match begins at the start of the string
(?:             # Start a non-capturing group that matches...
    -?          # an optional minus sign,
    \d+         # one or more digits
    (?:\.\d+)?  # an optional group that contains a dot and one or more digits.
    (?:         # Start of a non-capturing group that either matches...
       [+*/-]   # an operator
    |           # or
       $        # the end of the string.
    )           # End of inner non-capturing group
)+              # End of outer non-capturing group, required to match at least once.
(?<![+*/-])     # Make sure that the final character isn't an operator.
$               # Make sure that the match ends at the end of the string.

Test it live on regex101.com.

Tim Pietzcker
  • 328,213
  • 58
  • 503
  • 561
  • You man @Tim Pietzcker are the best. I dind't know that syntax (?: xx )? to do something optional. I've modified the '+' to '*' 'cause my app can accept an empty string... now I'm trying to add '(' ')' to do operation inside them, but I can't do it. I've tried something like: ^ (?: -?\d+(?:\.\d+)? (?:[+*/-]|$) (?:\(-?\d+(?:\.\d+)?(?:[+*/-]|\))\))? )+ $ [link]https://regex101.com/r/750sOO/5 But doesn't work. Can you help me? Just need '(n (+|-|*|/) m)' Thanks a lot – Miguel Camargo Rojas Apr 05 '19 at 17:25
  • As soon as you use parentheses (especially since they can be arbitrarily nested), you're leaving the realm of regular expressions. Python regexes can't recurse or count opening/closing parentheses. You need a context-free grammar/parser for that. – Tim Pietzcker Apr 05 '19 at 17:52
0

This answers your question about how to use if with regex:
Caveat: the regex formula will not weed out all invalid inputs, e.g., two decimal points (".."), two operators ("++"), and such. So please adjust it to suit your exact needs)

import re

regex = re.compile(r"[\d.+\-*\/]+")

input_list = [
    "53.22+22.11+10*555+62+55.2-66", "a53.22+22.11+10*555+62+55.2-66",
    "53.22+22.pq11+10*555+62+55.2-66", "53.22+22.11+10*555+62+55.2-66zz",
]

for input_str in input_list:
    mmm = regex.match(input_str)
    if mmm and input_str == mmm.group():
        print('Valid: ', input_str)
    else:
        print('Invalid: ', input_str)

Above as a function for use with a single string instead of a list:

import re
regex = re.compile(r"[\d.+\-*\/]+")

def check_for_valid_string(in_string=""):
    mmm = regex.match(in_string)
    if mmm and in_string == mmm.group():
        return 'Valid: ', in_string
    return 'Invalid: ', in_string

check_for_valid_string('53.22+22.11+10*555+62+55.2-66')
check_for_valid_string('a53.22+22.11+10*555+62+55.2-66')
check_for_valid_string('53.22+22.pq11+10*555+62+55.2-66')
check_for_valid_string('53.22+22.11+10*555+62+55.2-66zz')

Output:

## Valid:  53.22+22.11+10*555+62+55.2-66
## Invalid:  a53.22+22.11+10*555+62+55.2-66
## Invalid:  53.22+22.pq11+10*555+62+55.2-66
## Invalid:  53.22+22.11+10*555+62+55.2-66zz
SanV
  • 855
  • 8
  • 16