#php #regex #validation
#php #регулярное выражение #проверка
Вопрос:
Мне нужно получить значение из массива, используя точечную нотацию. Например:
$arr = [
'first' => [
'second' => [
'third' => 'hello'
]
]
];
$value = array_dot($arr, 'first.second.third'); // returns "hello"
Итак, что мне нужно сделать, это проверить, является ли это допустимой строкой, с помощью которой мы могли бы получить значение из массива.
Ограничения:
- только символы, не содержащие пробелов
- содержит хотя бы одну точку
- невозможно начать или закончить точкой
- перед и после каждой точки должна быть подстрока, не являющаяся точкой
Случаи:
`value.inside.array` valid
`val-2.of.array` valid
`.var2.in.arr` invalid
`dot.notation.` invalid
`value. dot` invalid
`consecutive....dots` invalid
Комментарии:
1. Должен
consecutive....dots
быть допустимый путь?2. @mickmackusa нет.
Ответ №1:
Допустимый путь, насколько я понимаю, будет начинаться с одной или нескольких не-точек, затем за ним последует одна или несколько последовательностей точки, затем одна или несколько не-точек (повторяется по мере необходимости до конца строки).
Вот эта логика в шаблоне регулярных выражений.
Код: (Демо)
$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)
);
Вывод:
array (
0 => 'value.inside.array',
1 => 'val-2.of.array',
6 => 'a.b.c.d.e.f',
)
Или разрешить последовательные точки с этим шаблоном: (Демо)
~^[^.s] .S*[^.s]$~
Комментарии:
1. избегать последовательных точек имеет смысл @mickmackusa!
2. Я не совсем уверен. Ключ массива может быть пустым. 3v4l.org/uloop Это может быть субъективным решением для ОП.
3. Я поддерживаю этот ответ, поскольку он правильно обрабатывает все крайние случаи (в отличие от принятого решения).
Ответ №2:
Попробуйте это:
^[^.s]S*.S*[^.s]$
Объяснение:
^[^.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
Демонстрация здесь.
Комментарии:
1. Сравните свой вывод с моим в этой демонстрации: 3v4l.org/hplm8
2. Я получил хорошие ответы от всех, но почему-то этот мне нравится больше всего. Ваше здоровье.
Ответ №3:
Я бы использовал preg_match_all
здесь соответствующий шаблон регулярных выражений. Мы можем сначала сформировать разделенную пробелом единственную строку из всех входных терминов, используя implode()
. Затем используйте регулярное выражение сопоставить все, чтобы найти совпадающие термины.
$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]);
Это выводит:
Array
(
[0] => value.inside.array
[1] => val-2.of.array
)
Вот объяснение шаблона регулярных выражений:
(?<!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
Комментарии:
1.Быть или не быть, вот в
....
чем вопрос.2. @mickmackusa Нет, это точечная нотация для массивов, обычно используемая в Laravel, как средство доступа к ключам внутри ассоциативного массива.
3. @Amir если ответ таков
No
, то два других ответа будут полезны вам не во всех случаях, и мой ответ является единственным правильным на странице, и вы приняли неправильный ответ.