PHP строка поиска (с подстановочными знаками) - PullRequest
7 голосов
/ 21 февраля 2010

Есть ли способ поместить подстановочный знак в строку? Причина, по которой я спрашиваю, заключается в том, что в настоящее время у меня есть функция для поиска подстроки между двумя подстроками (т.е. захват содержимого между «my» и «has блох» в предложении «у моей собаки есть блохи», в результате чего «собака») ).

function get_string_between($string, $start, $end){ 
    $string = " ".$string; 
    $ini = strpos($string,$start); 
    if ($ini == 0) return ""; 
    $ini += strlen($start); 
    $len = strpos($string,$end,$ini) - $ini; 
    return substr($string,$ini,$len); 
} 

Что я хочу сделать - это выполнить поиск с подстановочным знаком в строке. Скажем, я ищу между «% WILDCARD%» и «есть блохи» в предложении «У моей собаки есть блохи» - это все равно выдает «собака».

Не знаю, объяснил ли я это слишком хорошо, но, надеюсь, кто-то меня поймет: P. Большое спасибо за чтение!

Ответы [ 5 ]

9 голосов
/ 21 февраля 2010

Это один из немногих случаев, когда регулярные выражения действительно полезны. :)

if (preg_match('/my (\w+) has/', $str, $matches)) {
    echo $matches[1];
}

См. Документацию для preg_match .

3 голосов
/ 24 ноября 2013

шаблон подстановочного знака может быть преобразован в шаблон регулярного выражения, как это

function wildcard_match($pattern, $subject) {
  $pattern = strtr($pattern, array(
    '*' => '.*?', // 0 or more (lazy) - asterisk (*)
    '?' => '.', // 1 character - question mark (?)
  ));
  return preg_match("/$pattern/", $subject);
}

если строка содержит специальные символы, например, \. + *? ^ $ | {} / '#, они должны быть \ -экранированы

не проверено:

function wildcard_match($pattern, $subject) {
  // quotemeta function has most similar behavior,
  // it escapes \.+*?^$[](), but doesn't escape |{}/'#
  // we don't include * and ?
  $special_chars = "\.+^$[]()|{}/'#";
  $special_chars = str_split($special_chars);
  $escape = array();
  foreach ($special_chars as $char) $escape[$char] = "\\$char";
  $pattern = strtr($pattern, $escape);
  $pattern = strtr($pattern, array(
    '*' => '.*?', // 0 or more (lazy) - asterisk (*)
    '?' => '.', // 1 character - question mark (?)
  ));
  return preg_match("/$pattern/", $subject);
}
3 голосов
/ 19 мая 2011

Я согласен, что регулярные выражения гораздо более гибкие, чем подстановочные знаки, но иногда все, что вам нужно, это простой способ определения шаблонов. Для людей, которые ищут портативное решение (не только * NIX), вот моя реализация функции:

function wild_compare($wild, $string) {
    $wild_i = 0;
    $string_i = 0;

    $wild_len = strlen($wild);
    $string_len = strlen($string);

    while ($string_i < $string_len && $wild[$wild_i] != '*') {
        if (($wild[$wild_i] != $string[$string_i]) && ($wild[$wild_i] != '?')) {
            return 0;
        }
        $wild_i++;
        $string_i++;
    }

    $mp = 0;
    $cp = 0;

    while ($string_i < $string_len) {
        if ($wild[$wild_i] == '*') {
            if (++$wild_i == $wild_len) {
                return 1;
            }
            $mp = $wild_i;
            $cp = $string_i + 1;
        }
        else
        if (($wild[$wild_i] == $string[$string_i]) || ($wild[$wild_i] == '?')) {
            $wild_i++;
            $string_i++;
        }
        else {
            $wild_i = $mp;
            $string_i = $cp++;
        }
    }

    while ($wild[$wild_i] == '*') {
        $wild_i++;
    }

    return $wild_i == $wild_len ? 1 : 0;
}

Естественно, реализация PHP медленнее, чем fnmatch (), но она будет работать на любой платформе.

Может использоваться следующим образом:

if (wild_compare('regex are * useful', 'regex are always useful') == 1) {
    echo "I'm glad we agree on this";
}
2 голосов
/ 21 февраля 2010

Используйте регулярное выражение.

$string = "My dog has fleas";
if (preg_match("/\S+ (\S+) has fleas/", $string, $matches))
  echo ($matches[1]);
else
  echo ("Not found");

\S означает любой непробельный символ, + означает один или несколько предыдущих элементов, поэтому \S+ означает совпадение с одним или несколькими непробельными символами. (…) означает захват содержимого субматча и его помещение в массив $matches.

0 голосов
/ 26 октября 2010

Если вы настаиваете на использовании подстановочного знака (и да, PREG намного лучше), вы можете использовать функцию fnmatch , который работает только на * NIX.

Приветствия

...