Need help to fix this messy code
Hello everyone, I've got an Android application I'm developing and I need to restrict the user from entering certain symbols but allow others. Ones I'm allowing are
[ .:,/_-]
What I did:
binding.address = s?.replace("[^A-Za-z0-9 .:,/_-]".toRegex(), "")
?.replace("\\s+".toRegex(), " ")
?.replace("\\.{2,}".toRegex(), ".")
?.replace(":{2,}".toRegex(), ":")
?.replace(",{2,}".toRegex(), ",")
?.replace("_{2,}".toRegex(), "_")
?.replace("-{2,}".toRegex(), "-")
?.replace("/{2,}".toRegex(), "/")
As you can see it looks like a mess, and doesn't event work properly. How would I capture this? Requirements are:
- The first character can only be alphanumeric, so no symbols or a whitespace
- No symbol can be typed after another, so no multiple whitespaces or a colon, then a whitespace, then a dot, then maybe a comma and no whitespace between symbols
- A whitespace after a symbol is OK as well but that whitespace can only be followed by an alphanumeric character
Posted Oct 25, 2022, 12:49 PM UTC · edited
29
It looks like you're both identifying issues, and trying to clean issues (using the
.replace(…)). It would also help to include positive and negative test cases of what should/shouldn't pass.It looks like your expressions are trying to prevent the same character from being repeated (e.g. "
::"), while your prose/description makes it sound like none of those symbols should be successive (":_").For only a check, it looks like this regex should codify the requirements as I understand them based on your prose:
as demonstrated here: https://regex101.com/r/Ef3yfp/1
Look at that monstoristy. I could never. Thank you so so much! I'll try it ASAP.
If you look at the breakdown over on the regex101 site, it's not too bad, roughly translating to "an alphanumeric must be at the beginning, then one of the following three things must come next: either a punctuation that isn't followed by another punctuation, a punctuation followed by a space followed by an alphanumeric, or 1+ alphanumerics; and any number of those can happen as long as you then reach the end of the string"
Thanks for also explaining it. You're a godsend!
I think you need to make the + possessive to avoid potential catastrophic backtracking. Trying to match this string
aaaaaaaaaaaaaaaa__gives me a 'catastrophic backtracking' error on regex101.https://regex101.com/r/Ef3yfp/2
Making the + possessive should mitigate that:
https://regex101.com/r/Ef3yfp/3
Otherwise, if not supported, I would suggest removing the + even with the small performance difference.
thanks for catching that
I've never heard of "making the + possessive" (I knew about the greedy modifier)
I think that simply removing that "+" should be enough to prevent the catastrophic back-tracking, and shouldn't really impose any particular performance issues.
Thanks again for catching that!
You are welcome. I did not know about possessive quantifiers either until pretty long after I started learning about regex. But they are really neat but unfortunately not supported in all engines. Basically possessive quantifiers does not give back once they matched, stopping backtracking for that part of the expression.
More info: https://www.regular-expressions.info/possessive.html
In this case using ++ instead of removing the + should give a small performance improvement.
Thank you both! I guess this is why my app was crashing when I tried to match strings I knew wouldn't match.
Yes, that would be why. :)
It has been a bug on big websites as well, if they use RegExs with this problem. But your app should work as expected now.