Regular Expression to test if input is an ok substring from the pattern

552 Views Asked by At

Basically, if I've a RegEx like

/^(foo|bars)$/

I'd like it to be successful for

['', 'f', 'fo', 'foo', 'b', 'ba', 'bar', 'bars']

but then fail for the likes of

['j', 'fa', 'foos'...]

I was aware of some of the answers that have been given,

/^(f(oo?)?|b(ar?)?)$/

or

/^f|fo|foo|b|ba|bar$/

and while they do work, for this specific case, that's not the way I'd rather go, if this were expanded to 20 long words, it becomes unmanageable. I'd love a more elegant solution if it's possible.

Any elegant ideas? Where I'm using it, I can, rather than a RegEx, pass a list of Strings, then just check if the index of the input is 0 for any of the Strings, but I just wanted to see if there's a way you can do it with a Regular Expression.

Thanks for all the answers, but I'm mostly looking for a as-much-as-possible 'elegant' solution, but after looking through, I'm not sure if there is one.

Basically, it's a forced input prevention. What I wanted was similar to Dojo's ValidationTextBox, http://dojotoolkit.org/reference-guide/1.7/dijit/form/ValidationTextBox.html. There, it tells you as soon as possible if the input doesn't have a match to the validation pattern (which I... might end up doing), but I'd like to only allow correct input, and the path to it.

To rephrase, I was trying to find out if there was any elegant way to see if you could check the input string only against a pattern of it's same length, as in, if you only typed one character, it'd really only test against

/^(f|b)$/

in this case, two characters,

/^(fo|ba)$/

and so on.

While my specific answer is about alternation with regular expression, I'd love to know this about regular expression in general (from what I've read, it doesn't seem possible though).

I mean, if you had,

/^The dog$/

I'd like a way for a test to be successful for all of

['', 'T', 'Th',...'The dog']
4

There are 4 best solutions below

0
On

/f|fo|foo|b|ba|bar/

Oops! Your answer couldn't be submitted because:

body must be at least 30 characters; you entered 19

0
On

Here is an option:

/^(f(oo?)?|b(ar?)?)$/

I am assuming you want the entire string to match these and nothing else, since if it is okay to find a partial match then it is equivalent to just checking for the first character of either substring anywhere in the string (/[fb]/).

Here is an example with longer strings, using 'hello' and 'world' instead of 'foo' and 'bar':

/^(h(e(l(lo?)?)?)?|w(o(r(ld?)?)?)?)$/

It would require some more characters, but you could use non-capturing groups to improve the efficiency a bit:

/^(?:h(?:e(?:l(?:lo?)?)?)?|w(?:o(?:r(?:ld?)?)?)?)$/
2
On

You could write your regex like this:

http://fiddle.re/p73n (Links to regexplanet)

(fo?o?|ba?r?).

If the list of words doesn't change often and isn't large, that might be a good solution. Is the list of words is rather dynamic, you might want to check if an entry.starstWith(yourInput).

Cheers.

2
On

What technology are you using?

I ask because an 'elegant' technical solution might be to write a program which generates a regex pattern from the allowed input strings for you, rather than try to build it by hand.

If this is in an interactive application with single character input, there is a similar strategy (write a program to create the regex), but generate one regex pattern for 1 character input, one for 2 chars, one for 3 chars, etc, which would be selected based on the input length.

For fixed strings, I'd be tempted to do something like:

for each string:
    if string has a character match at the nth position:
        retain string
    else:
        remove string from further consideration

That would support completion too, i.e. signal to the user that there is no need to type anything more as there is only one possible matching string.