0

I am trying to create regular expression that will validate simple patterns. Here a lists of valid and invalid patterns.

Valid:

foo, foo.bar, foo.bar.baz,
*, *.foo, foo.*, *.foo.*, *.foo.bar, foo.*.bar, foo.bar.*, *.foo.bar.*,
**, **.foo, foo.**, **.foo.**, **.foo.bar, foo.**.bar, foo.bar.**, **.foo.bar.**

And invalid:

<empty string>, null, false, true, foo bar baz,
.foo, foo., .foo.,
***, ***.foo, foo.***, ***.foo.*, foo.***.bar

So allowed marks are * and **. I spent a lot of time trying to write a regexp for those patterns, and best solution was:

/(\.|^)(\w+|\*{1,2})(?=\.|$)/

But it doesn't check whole patten, just finds it parts, so I cannot validate using preg_match. Another problem is that .foo pattern is valid according to that regexp, but it shouldn't because of dot in the beginning.

What did I miss?

3 Answers 3

2

Use this regex:

/^(\*{1,2}|[a-z]+)(\.(\*{1,2}|[a-z]+))*$/i

Here is sample code to test it by validating that all of the "good" patterns match, but not the "bad" ones. It correctly handles every one of the examples you gave.

$good_data = array(
    'foo',
    'foo.bar',
    'foo.bar.baz',
    '*',
    '*.foo',
    'foo.*',
    '*.foo.*',
    '*.foo.bar',
    'foo.*.bar',
    'foo.bar.*',
    '*.foo.bar.*',
    '**',
    '**.foo',
    'foo.**',
    '**.foo.**',
    '**.foo.bar',
    'foo.**.bar',
    'foo.bar.**',
    '**.foo.bar.**'
    );
$bad_data = array(
    '',
    null,
    false,
    true,
    'foo bar baz',
    '.foo',
    'foo.',
    '.foo.',
    '***',
    '***.foo',
    'foo.***',
    '***.foo.*',
    'foo.***.bar'
    );
$regex = "/^(\*{1,2}|[a-z]+)(\.(\*{1,2}|[a-z]+))*$/i";
foreach($good_data as $data) {
    echo (preg_match($regex, $data) ? "pass" : "FAIL: $data")."<br/>";
}
foreach($bad_data as $data) {
    echo (!preg_match($regex, $data) ? "pass" : "FAIL: $data")."<br/>";
}
Sign up to request clarification or add additional context in comments.

Comments

1

You can use this regex:

/^(?!(null|true|false|)$)(\*{1,2}\.?)?(\w+(\.\w+)*(\.?\*{1,2})?)?$/

1 Comment

it fails on foo.*.bar on foo.**.bar, but matches *foo and foo*
0

Here's another option too, if you specifically want to single out foo, bar, and/or baz (all optionally) as valid:

/((\*+|(foo|bar|baz)+)(\.(\*+|(foo|bar|baz)+))*)/

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.