#php #regex #string-matching
#php #регулярное выражение #сопоставление строк
Вопрос:
Я хочу предоставить возможность сопоставлять строку с подстановочным знаком *
.
Пример
$mystring = 'dir/folder1/file';
$pattern = 'dir/*/file';
stringMatchWithWildcard($mystring,$pattern); //> Returns true
Пример 2:
$mystring = 'string bl#abla;y';
$pattern = 'string*y';
stringMatchWithWildcard($mystring,$pattern); //> Returns true
Я подумал что-то вроде:
function stringMatch($source,$pattern) {
$pattern = preg_quote($pattern,'/');
$pattern = str_replace( '*' , '.*?', $pattern); //> This is the important replace
return (bool)preg_match( '/^' . $pattern . '$/i' , $source );
}
В основном замена *
на .*?
(учитывая, что в *nix
среде *
соответствует empty
строке) ©vbence
Какие-либо улучшения / предложения?
// Добавлено return (bool)
, потому что preg_match возвращает int
Ответ №1:
preg_match
Здесь нет необходимости. В PHP есть функция сравнения подстановочных знаков, специально созданная для таких случаев:
И fnmatch('dir/*/file', 'dir/folder1/file')
, вероятно, уже сработало бы для вас. Но будьте осторожны, что *
подстановочный знак также добавит дополнительные косые черты, как это сделал бы preg_match .
Комментарии:
1. привет, Марио. в fnmatches есть еще какая-то функция, подобная
[]
. Мне просто нужно*
как «специальный символ»2. fnmatch не поддерживается в системах, отличных от POSIX. (Я вижу, что php5.3 теперь также поддерживает Windows). Так что это не всегда лучший способ
Ответ №2:
Вместо этого вы должны просто использовать .*
.
$pattern = str_replace( '*' , '.*', $pattern); //> This is the important replace
Редактировать: Также ваши ^
и $
были в неправильном порядке.
<?php
function stringMatchWithWildcard($source,$pattern) {
$pattern = preg_quote($pattern,'/');
$pattern = str_replace( '*' , '.*', $pattern);
return preg_match( '/^' . $pattern . '$/i' , $source );
}
$mystring = 'dir/folder1/file';
$pattern = 'dir/*/file';
echo stringMatchWithWildcard($mystring,$pattern);
$mystring = 'string bl#abla;y';
$pattern = 'string*y';
echo stringMatchWithWildcard($mystring,$pattern);
Рабочая демонстрация: http://www.ideone.com/mGqp2
Комментарии:
1. Я не знаю, хочу ли я предоставить возможность сопоставлять это
'dir//file'
с'dir/*/file'
2.
.*
является жадным, оно съест всю оставшуюся часть вашей строки, а не только минимальное количество символов для продолжения шаблонов. Так что, если у вас есть что-нибудь после.*
, результат всегда будет false.3. Я думал, что это именно то, что вы хотели сделать с
. ?
из вашего описания.4. @vbence
preg_match('/.*a/', 'aa')
?5. Хорошо, похоже,
match
это даст те же результаты.
Ответ №3:
. ?
Вызывает не жадное сопоставление для всех символов. Это НЕ равно «*», потому что оно не будет соответствовать пустой строке.
Следующий шаблон также будет соответствовать пустой строке:
.*?
итак…
stringMatchWithWildcard ("hello", "hel*lo"); // will give true
Комментарии:
1. как вы думаете, я должен разрешить пустую строку? Также рассмотрим dir:
'dir//file'
соответствие'dir/*/file'
?2. Если вы хотите, чтобы это работало аналогично тому, как работают оболочки операционной системы, тогда вы должны разрешить пустую строку. Просто попробуйте,
echo > hello
за которымdir hello*
следует в Windows илиls hello*
в * nix. В этом контексте * соответствует пустой строке.3. Было бы вежливо дать комментарий с вашим -1.
4. ах, здорово! спасибо за сравнение * nix! (также я не получил -1 вашего ответа, у меня нет причин это делать)
5. @yes123 Да, я знаю, не обвиняю. 🙂
Ответ №4:
Вы путаете окончание ( $
) и начало ( ^
). Это:
preg_match( '/$' . $pattern . '^/i' , $source );
Должно быть:
preg_match( '/^' . $pattern . '$/i' , $source );
Ответ №5:
Единственная проблема, с которой вы столкнетесь, заключается в том, что вызов preg_quote()
будет экранировать символ звездочки. Учитывая это, ваш str_replace()
заменит *
, но не escape-символ перед ним.
Поэтому вам следует изменить str_replace('*' ..)
на str_replace('*'..)
Комментарии:
1. я пропустил это из документа, к сожалению. исправлено
Ответ №6:
$pattern = str_replace( '*' , '. ?', $pattern); // at least one character
Комментарии:
1. Пожалуйста, добавьте некоторые пояснения к вашему коду — взгляните на другие ответы на этот вопрос для некоторого вдохновения