Amir Rami
Amir Rami

Reputation: 405

Regex to match a string that contains substrings separated with dots

I need to get a value from an array using the dot notation. For example:

$arr = [
    'first' => [
        'second' => [
            'third' => 'hello'
        ]
    ]
];

$value = array_dot($arr, 'first.second.third'); // returns "hello"

So what I need to do is check if it's a valid string by which we could get a value from array.

Constraints:

Cases:

`value.inside.array` valid
`val-2.of.array` valid
`.var2.in.arr` invalid
`dot.notation.` invalid
`value. dot` invalid
`consecutive....dots` invalid

Upvotes: 1

Views: 983

Answers (3)

mickmackusa
mickmackusa

Reputation: 48041

A valid path, as far as I understand, will start with one or more non-dots, then it will be followed by one or more sequences of a dot then one or more non-dots (repeated as necessary to the end of the string).

Here is that logic in a regex pattern.

Code: (Demo)

$array = [
    "value.inside.array",
    "val-2.of.array",
    ".var2.in.arr",
    "dot.notation.",
    "value. dot",
    "consecutive....dots",
    "a.b.c.d.e.f"
];

var_export(
    preg_grep('~^[^.\s]+(?:\.[^.\s]+)+$~', $array)
);

Output:

array (
  0 => 'value.inside.array',
  1 => 'val-2.of.array',
  6 => 'a.b.c.d.e.f',
)

Or allow consecutive dots with this pattern: (Demo)

~^[^.\s]+\.\S*[^.\s]$~

Upvotes: 3

kaza
kaza

Reputation: 2327

Try this:

^[^.\s]\S*\.\S*[^.\s]$

Explanation:

^[^.\s]     Start with any non-dot and non-white character
\S*             Any non space characters
\.              Force at least one dot
\S*             Any non space characters
[^.\s]$    End with any non-dot and non-white character

Demo here.

Upvotes: 1

Tim Biegeleisen
Tim Biegeleisen

Reputation: 522636

I would use preg_match_all here with an appropriate regex pattern. We can first form a space-separated single string of all input terms using implode(). Then, use a regex match all to fish out matching terms.

$array = ["value.inside.array", "val-2.of.array", ".var2.in.arr", "dot.notation.", "value. dot"];
$input = implode(" ", $array);
preg_match_all("/(?<!\S)[^.\s]\S*\.\S*[^.\s](?!\S)/", $input, $matches);
print_r($mstches[0]);

This prints:

Array
(
    [0] => value.inside.array
    [1] => val-2.of.array
)

Here is an explanation of the regex pattern:

(?<!\S) assert that what precedes is either whitespace or the start of the string
[^.\s]  first character is non whitespace other than dot
\S*     match zero or more non whitespace characters
\.      match a dot
\S*     match zero or more non whitespace characters
[^.\s]  final character is non whitespace other than dot
(?!\S)  assert that what follows is either whitespace or the start of the string

Upvotes: 1

Related Questions