Regex in lex [^a-z]* - regex

For the given regex, [^a-z]* in lex, the question is will it match any word not containing any lower case letter, or this is not the correct implementation? I.e., for that specific scenario, should the given regex be used, or this is a proper one for matching a word that has no lower case letters: [^a-z]+?
My reasoning is that it is not, it should be + instead of the *, since the negation of range, with 0 or more possible cases. seems wrong. But it's hard to get my mind on why is it wrong. I tried several regex tools online, and its hit and miss, some manage to show that it works, some show more matches between characters.
I would say that negating a lowercase string, and saying its either 0 or more of those, that would match the string abc as well, since it (does satisfy the scenario that it doesn't have 0 of anything. That could be said for any string. + seems like a more intuitive option, but in this case * was used and I think its an incorrect implementation, but can't find any resources to back it up since Google doesn't play nicely with those search strings.
Some test cases, this is is node.js:
/[^a-z]*$/.test('testTEST123') - True
/[^a-z]*$/.test('test') - True (this one should be false as per problem statement)
/[^a-z]+$/.test('testTEST123') - True
/[^a-z]+$/.test('test') - False (this one is correct, so there are no matches that dont satisfy the regex)
On regex101.com, the results are similar, but the highlighted part is the end of the line, although there are no characters there.
I dont know is there some specific lex implementation of regex that is different, but as I described, something feels wrong with * usage for not-matching the range.

(F)lex rules never match the empty string, so it does not make any difference whether you use * or + in this context.
But I don't think the question captures the behaviour. A (f)lex rule matches the longest string matching any pattern and [^a-z]+ will match any sequence of characters, whether punctuation, white space, unprintable control codes, etc., except lower-case letters. (In other words, it does not just match "words" unless you have an unusual definition of "word".

Related

Regex to match hexadecimal and integer numbers [duplicate]

In a regular expression, I need to know how to match one thing or another, or both (in order). But at least one of the things needs to be there.
For example, the following regular expression
/^([0-9]+|\.[0-9]+)$/
will match
234
and
.56
but not
234.56
While the following regular expression
/^([0-9]+)?(\.[0-9]+)?$/
will match all three of the strings above, but it will also match the empty string, which we do not want.
I need something that will match all three of the strings above, but not the empty string. Is there an easy way to do that?
UPDATE:
Both Andrew's and Justin's below work for the simplified example I provided, but they don't (unless I'm mistaken) work for the actual use case that I was hoping to solve, so I should probably put that in now. Here's the actual regexp I'm using:
/^\s*-?0*(?:[0-9]+|[0-9]{1,3}(?:,[0-9]{3})+)(?:\.[0-9]*)?(\s*|[A-Za-z_]*)*$/
This will match
45
45.988
45,689
34,569,098,233
567,900.90
-9
-34 banana fries
0.56 points
but it WON'T match
.56
and I need it to do this.
The fully general method, given regexes /^A$/ and /^B$/ is:
/^(A|B|AB)$/
i.e.
/^([0-9]+|\.[0-9]+|[0-9]+\.[0-9]+)$/
Note the others have used the structure of your example to make a simplification. Specifically, they (implicitly) factorised it, to pull out the common [0-9]* and [0-9]+ factors on the left and right.
The working for this is:
all the elements of the alternation end in [0-9]+, so pull that out: /^(|\.|[0-9]+\.)[0-9]+$/
Now we have the possibility of the empty string in the alternation, so rewrite it using ? (i.e. use the equivalence (|a|b) = (a|b)?): /^(\.|[0-9]+\.)?[0-9]+$/
Again, an alternation with a common suffix (\. this time): /^((|[0-9]+)\.)?[0-9]+$/
the pattern (|a+) is the same as a*, so, finally: /^([0-9]*\.)?[0-9]+$/
Nice answer by huon (and a bit of brain-twister to follow it along to the end). For anyone looking for a quick and simple answer to the title of this question, 'In a regular expression, match one thing or another, or both', it's worth mentioning that even (A|B|AB) can be simplified to:
A|A?B
Handy if B is a bit more complex.
Now, as c0d3rman's observed, this, in itself, will never match AB. It will only match A and B. (A|B|AB has the same issue.) What I left out was the all-important context of the original question, where the start and end of the string are also being matched. Here it is, written out fully:
^(A|A?B)$
Better still, just switch the order as c0d3rman recommended, and you can use it anywhere:
A?B|A
Yes, you can match all of these with such an expression:
/^[0-9]*\.?[0-9]+$/
Note, it also doesn't match the empty string (your last condition).
Sure. You want the optional quantifier, ?.
/^(?=.)([0-9]+)?(\.[0-9]+)?$/
The above is slightly awkward-looking, but I wanted to show you your exact pattern with some ?s thrown in. In this version, (?=.) makes sure it doesn't accept an empty string, since I've made both clauses optional. A simpler version would be this:
/^\d*\.?\d+$/
This satisfies your requirements, including preventing an empty string.
Note that there are many ways to express this. Some are long and some are very terse, but they become more complex depending on what you're trying to allow/disallow.
Edit:
If you want to match this inside a larger string, I recommend splitting on and testing the results with /^\d*\.?\d+$/. Otherwise, you'll risk either matching stuff like aaa.123.456.bbb or missing matches (trust me, you will. JavaScript's lack of lookbehind support ensures that it will be possible to break any pattern I can think of).
If you know for a fact that you won't get strings like the above, you can use word breaks instead of ^$ anchors, but it will get complicated because there's no word break between . and (a space).
/(\b\d+|\B\.)?\d*\b/g
That ought to do it. It will block stuff like aaa123.456bbb, but it will allow 123, 456, or 123.456. It will allow aaa.123.456.bbb, but as I've said, you'll need two steps if you want to comprehensively handle that.
Edit 2: Your use case
If you want to allow whitespace at the beginning, negative/positive marks, and words at the end, those are actually fairly strict rules. That's a good thing. You can just add them on to the simplest pattern above:
/^\s*[-+]?\d*\.?\d+[a-z_\s]*$/i
Allowing thousands groups complicates things greatly, and I suggest you take a look at the answer I linked to. Here's the resulting pattern:
/^\s*[-+]?(\d+|\d{1,3}(,\d{3})*)?(\.\d+)?\b(\s[a-z_\s]*)?$/i
The \b ensures that the numeric part ends with a digit, and is followed by at least one whitespace.
Maybe this helps (to give you the general idea):
(?:((?(digits).^|[A-Za-z]+)|(?<digits>\d+))){1,2}
This pattern matches characters, digits, or digits following characters, but not characters following digits.
The pattern matches aa, aa11, and 11, but not 11aa, aa11aa, or the empty string.
Don't be puzzled by the ".^", which means "a character followd by line start", it is intended to prevent any match at all.
Be warned that this does not work with all flavors of regex, your version of regex must support (?(named group)true|false).

Efficient Regex for requiring a specific sentence pattern but allowing html etc

(As is often the case, while writing this, I think I fixed the expression itself so it now works for my purposes, so efficiency is now my main concern - but I would still like input as to whether the expression can be improved or will let through way more than it should, so I have left the entire explanation in.)
I am trying to write a regular expression which will validate that user-submitted text matches a length requirement. Users must write 7 or more full sentences of 4 or more words. We are defining this as follows:
- 4 words means 3 or more sections of '1 or more non-space characters followed by 1 or more spaces', then 1 instance of '1 or more non-space characters optionally followed by a space' (because some people like to put spaces before their punctuation marks I guess)
- A sentence is ended with a punctuation mark (.?!)
- Zero or more spaces are allowed after each sentence
- (Repeat 7 times)
This definition can be changed to anything sensible, but that's what I came up with so far. Which gives me the following RegEx:
((\S+\s+){3,}\S+[.?!]\s*){7,}
This seems to work, but I have obviously fudged many things and wonder if anyone has a better idea. (It has to allow for html at any point, and a lot of other quirks from users' writing. I am not too concerned about people gaming the system - there are still manual checks, this is just a first-stage check to lighten the load.)
My other main concern is efficiency - I'm new to regex and don't know what is a 'normal' calculation time, but the debugger(s) I'm using are struggling at times when I paste in a block of text to check, and I don't know if this is caused by my RegEx or the debugger. It is often timing out on longer sections of text where there is no match. Is there a more efficient way to do what I'm wanting...?
First, when doing full text match, always surround the regex with ^...$. ^ anchors the start of the regex to the start of the validation string, and $ anchors the end of the regex to the end of the string. Otherwise, if it fails to match, it will repeat the validation attempt starting on every single character (Which, at minimum (4 words * 3 spaces) * 7 sentences = excessive amount of work).
Second, always use mutually exclusive groups where you can. \S (anything not white-space) includes the characters .?!, So on failing to find punctuation, it has to backtrack and retry each \S it matched. (Namely, because the first pass would mark it as a word instead of punctuation) So I would recommend replace \S with a more mutually exclusive "anything not white-space or punctuation" [^\s.?!]. Note that that [] contains a lowercase s instead of an uppercase one. [^...] is "match any character NOT in this group".
Those 2 things will drop you from catastrophic backtracking to a reasonable ~1-3k steps depending on paragraph length.
UPDATE:
If you would allow a small alteration to the validation logic, making it so that multiple short sentences can count together as one sentence, then the following regex should do.
^(\s*(\S+\s+){3}([.?!]\s*)?([^\s.?!]+\s+)*\S+\s*[.?!]){7,}$
This hybrid version will allow short sentences without causing catastrophic backtracking. Without the small rule change, you will need to nest a variable length pattern inside a variable length pattern; which is catastrophic when the pattern isn't fully mutually exclusive. (updated demo)
Also, technically you can replace {7,}$ with just {7} if once 7 sentences have been found, you don't care what comes after that. (That will let the regex stop as soon as minimal viability is found, which would be more accepting of some extreme edge cases)
(You can play with it here on regex101.com)

What do we need Lookahead/Lookbehind Zero Width Assertions for?

I've just learned about these two concepts in more detail. I've always been good with RegEx, and it seems I've never seen the need for these 2 zero width assertions.
I'm pretty sure I'm wrong, but I do not see why these constructs are needed. Consider this example:
Match a 'q' which is not followed by a 'u'.
2 strings will be the input:
Iraq
quit
With negative lookahead, the regex looks like this:
q(?!u)
Without it, it looks like this:
q[^u]
For the given input, both of these regex give the same results (i.e. matching Iraq but not quit) (tested with perl). The same idea applies to lookbehinds.
Am I missing a crucial feature that makes these assertions more valuable than the classic syntax?
Why your test probably worked (and why it shouldn't)
The reason you were able to match Iraq in your test might be that your string contained a \n at the end (for instance, if you read it from the shell). If you have a string that ends in q, then q[^u] cannot match it as the others said, because [^u] matches a non-u character - but the point is there has to be a character.
What do we actually need lookarounds for?
Obviously in the above case, lookaheads are not vital. You could workaround this by using q(?:[^u]|$). So we match only if q is followed by a non-u character or the end of the string. There are much more sophisticated uses for lookaheads though, which become a pain if you do them without lookaheads.
This answer tries to give an overview of some important standard situations which are best solved with lookarounds.
Let's start with looking at quoted strings. The usual way to match them is with something like "[^"]*" (not with ".*?"). After the opening ", we simply repeat as many non-quote characters as possible and then match the closing quote. Again, a negated character class is perfectly fine. But there are cases, where a negated character class doesn't cut it:
Multi-character delimiters
Now what if we don't have double-quotes to delimit our substring of interest, but a multi-character delimiter. For instance, we are looking for ---sometext---, where single and double - are allowed within sometext. Now you can't just use [^-]*, because that would forbid single -. The standard technique is to use a negative lookahead at every position, and only consume the next character, if it is not the beginning of ---. Like so:
---(?:(?!---).)*---
This might look a bit complicated if you haven't seen it before, but it's certainly nicer (and usually more efficient) than the alternatives.
Different delimiters
You get a similar case, where your delimiter is only one character but could be one of two (or more) different characters. For instance, say in our initial example, we want to allow for both single- and double-quoted strings. Of course, you could use '[^']*'|"[^"]*", but it would be nice to treat both cases without an alternative. The surrounding quotes can easily be taken care of with a backreference: (['"])[^'"]*\1. This makes sure that the match ends with the same character it began with. But now we're too restrictive - we'd like to allow " in single-quoted and ' in double-quoted strings. Something like [^\1] doesn't work, because a backreference will in general contain more than one character. So we use the same technique as above:
(['"])(?:(?!\1).)*\1
That is after the opening quote, before consuming each character we make sure that it is not the same as the opening character. We do that as long as possible, and then match the opening character again.
Overlapping matches
This is a (completely different) problem that can usually not be solved at all without lookarounds. If you search for a match globally (or want to regex-replace something globally), you may have noticed that matches can never overlap. I.e. if you search for ... in abcdefghi you get abc, def, ghi and not bcd, cde and so on. This can be problem if you want to make sure that your match is preceded (or surrounded) by something else.
Say you have a CSV file like
aaa,111,bbb,222,333,ccc
and you want to extract only fields that are entirely numerical. For simplicity, I'll assume that there is no leading or trailing whitespace anywhere. Without lookarounds, we might go with capturing and try:
(?:^|,)(\d+)(?:,|$)
So we make sure that we have the start of a field (start of string or ,), then only digits, and then the end of a field (, or end of string). Between that we capture the digits into group 1. Unfortunately, this will not give us 333 in the above example, because the , that precedes it was already part of the match ,222, - and matches cannot overlap. Lookarounds solve the problem:
(?<=^|,)\d+(?=,|$)
Or if you prefer double negation over alternation, this is equivalent to
(?<![^,])\d+(?![^,])
In addition to being able to get all matches, we get rid of the capturing which can generally improve performance. (Thanks to Adrian Pronk for this example.)
Multiple independent conditions
Another very classic example of when to use lookarounds (in particular lookaheads) is when we want to check multiple conditions on an input at the same time. Say we want to write a single regex that makes sure our input contains a digit, a lower case letter, an upper case letter, a character that is none of those, and no whitespace (say, for password security). Without lookarounds you'd have to consider all permutations of digit, lower case/upper case letter, and symbol. Like:
\S*\d\S*[a-z]\S*[A-Z]\S*[^0-9a-zA_Z]\S*|\S*\d\S*[A-Z]\S*[a-z]\S*[^0-9a-zA_Z]\S*|...
Those are only two of the 24 necessary permutations. If you also want to ensure a minimum string length in the same regex, you'd have to distribute those in all possible combinations of the \S* - it simply becomes impossible to do in a single regex.
Lookahead to the rescue! We can simply use several lookaheads at the beginning of the string to check all of these conditions:
^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[^0-9a-zA-Z])(?!.*\s)
Because the lookaheads don't actually consume anything, after checking each condition the engine resets to the beginning of the string and can start looking at the next one. If we wanted to add a minimum string length (say 8), we could simply append (?=.{8}). Much simpler, much more readable, much more maintainable.
Important note: This is not the best general approach to check these conditions in any real setting. If you are making the check programmatically, it's usually better to have one regex for each condition, and check them separately - this let's you return a much more useful error message. However, the above is sometimes necessary, if you have some fixed framework that lets you do validation only by supplying a single regex. In addition, it's worth knowing the general technique, if you ever have independent criteria for a string to match.
I hope these examples give you a better idea of why people would like to use lookarounds. There are a lot more applications (another classic is inserting commas into numbers), but it's important that you realise that there is a difference between (?!u) and [^u] and that there are cases where negated character classes are not powerful enough at all.
q[^u] will not match "Iraq" because it will look for another symbol.
q(?!u) however, will match "Iraq":
regex = /q[^u]/
/q[^u]/
regex.test("Iraq")
false
regex.test("Iraqf")
true
regex = /q(?!u)/
/q(?!u)/
regex.test("Iraq")
true
Well, another thing along with what others mentioned with the negative lookahead, you can match consecutive characters (e.g. you can negate ui while with [^...], you cannot negate ui but either u or i and if you try [^ui]{2}, you will also negate uu, ii and iu.
The whole point is to not "consume" the next character(s), so that it can be e.g. captured by another expression that comes afterwards.
If they're the last expression in the regex, then what you've shown are equivalent.
But e.g. q(?!u)([a-z]) would let the non-u character be part of the next group.

Regex to Match All Except a String

Given the string beginend where begin and end are both optional, I want to match the whole string and back-reference only begin. Begin is unknown but alpha-numeric; end is literally end. How would I go about doing this?
In case it matters, I'd be using this in a Textpad macro to replace "beginend" with something else including "begin".
To match an string of "alpha-numeric" characters that do not contain "end" you can use something like:
(?:(?!end)[A-Za-z\d])+
An expression like this would do what you ask:
^((?:(?!end)[A-Za-z0-9])+)(?:end)?\z
EDITED (see after blockquote)
I don't have commenting privileges, so I can't comment on his
solution, but Qtax's solution will not work because it assumes that
begin will never contain the substring "end", e.g., it wouldn't
match the string "sendingend".
My solution:
^([A-Za-z0-9]*)(?:end)?$
Of course, it also depends on what you mean by alphanumeric. My
example has the strictest definition, i.e., just upper- and lower-case
letters plus digits. You'd need to add in other characters if you want
them. If you want to include the underscore as well as those
characters, you can replace the whole bulky [A-Za-z0-9] with \w
(equivalent to [A-Za-z0-9_]). Add \s if you want whitespace.
Since you said your regex knowledge is limited, I'll explain the rest
of the solution to you and whoever else comes along.
^ and $ match the beginning and the end of the string, respectively. By including the $ in particular, you're
guaranteeing that the last "end" you encounter is really at the end.
For example, without them, it would still match the string
"sendingsending" and the rest of your program would think it's found
that "end" at the end. With these, it's still going to match
"sendingsending" because any characters are allowed (see below), but
other steps in your script will recognize the presence of
"end". It actually doesn't matter much for this current
string, because the ([A-Za-z0-9]*) will capture the entire string if
"end" is not present. However, you therefore need another regex to
ensure the presence or absence of "end"...so you'd do something like
(end)$ to locate it.
([A-Za-z0-9]*): the square brackets contain the specific characters that are allowed (you should definitely read up on this if
you don't know). The * means it will match one of those characters 0
or more times, so this allows for no string (i.e., just "end") as well
as super-long strings. The parentheses are capturing that pattern so
you can back-reference it.
(?:end)?: the last ? makes it match this pattern 0 or 1 times (i.e., makes it optional). The (?:string) structure allows you to
group characters together as you would with parentheses but the ?:
makes it not save that pattern, so it uses less memory. In your
case, that memory would be negligible, but it's nice to know for
future use.
If you need more help, try Googling 'regex'. There's tons of good
references. You can also test them out. My personal favourite tester
is called My Regex Tester.
Good luck!
I just tried looking up TextPad macros, and you might run into a problem. As I've explained above, to verify the presence of "end" at the end of the string, you'll need something separate. I was envisioning some kind of conditional, something like IF (end)$ THEN replace with ^([A-Za-z0-9]*)(?:end)?$ ELSE use the whole string. However, I don't know if you can do that with these macros...it's hard to say, because I'm not a TextPad user and there's next to no documentation. If you can't, then I think you're going to have to put some restrictions on it. One idea is to not allow "end" to be anywhere in the begin substring (which is how Qtax's solution did it). But now I'm wondering...if "end" if going to be optional, and if conditionals aren't allowed, what's the point of having it at all? ...perhaps I'm overthinking things. I await your reply.
Try using a positive look-ahead. This is a zero-width assertion so won't be included in the match. It also allows for the substring end to be present within the alpha-numeric string
([a-z0-9]*)(?=end)
What this is saying is: Match an alpha-numeric string only if it is immediately followed by end

Regular Expression to validate the field: field must contain atleast 2 AlphaNumeric characters

I need to validate VARCHAR field.
conditions are: field must contain atleast 2 AlphaNumeric characters
so please any one give the Regular Expression for the above conditions
i wrote below Expression but it will check atleast 2 letters are alphanumeric. and if my input will have other than alphanumeric it is nt validating.
'^[a-zA-Z0-9]{2,}$'
please help.........
[a-zA-Z0-9].*[a-zA-Z0-9]
The easy way: At least two alnum's anywhere in the string.
Answer to comments
I never did (nor intended to do) any benchmarking. Therefore - and given that we know nothing of OP's environment - I am not one to judge whether a non-greedy version ([a-zA-Z0-9].*?[a-zA-Z0-9]) will be more efficient. I do believe, however, that the performance impact is totally negligible :)
I would probably use this regular expression:
[a-zA-Z0-9][^a-zA-Z0-9]*[a-zA-Z0-9]
How broad is your definition of alphanumeric? For US ASCII, see the answers above. For a more cosmopolitan view, use one of
[[:alnum:]].*[[:alnum:]]
or
[^\W_].*[^\W_]
The latter works because \w matches a "word character," alphanumerics and underscore. Use a double-negative to exclude the underscore: "not not-a-word-character and not underscore."
As simple as
'\w.*\w'
In response to a comment, here's a performance comparison for the greedy [a-zA-Z0-9].*[a-zA-Z0-9] and the non-greedy [a-zA-Z0-9].*?[a-zA-Z0-9].
The greedy version will find the first alphanumeric, match all the way to the end, and backtrack to the last alphanumeric, finding the longest possible match. For a long string, it is the slowest version. The non greedy version finds the first alphanumeric, and tries not to match the following symbols until another alphanumeric is found (that is, for every letter it matches the empty string, tries to match [a-zA-Z0-9], fails, and matches .).
Benchmarking (empirical results):
In case the alphanumeric are very far away, the greedy version is faster (even faster than Gumbo's version).
In case the alphanumerics are close to each other, the greedy version is significantly slower.
The test: http://jsbin.com/eletu/4
Compares 3 versions:
[a-zA-Z0-9].*?[a-zA-Z0-9]
[a-zA-Z0-9][^a-zA-Z0-9]*[a-zA-Z0-9]
[a-zA-Z0-9].*[a-zA-Z0-9]
Conclusion: none. As always, you should check against typical data.