Php preg_match с подстановочными знаками - PullRequest
0 голосов
/ 13 апреля 2020

У меня есть некоторый почтовый индекс в массиве, который включает некоторые символы подстановки, подобные этому

$zip_codes = array( '12556', '765547', '234*', '987*' );
$target_zip = '2347890';

Итак, чтобы проверить, присутствует ли целевой массив в массиве. Я делаю так

foreach( $zip_codes as $zip ) {
  if ( preg_match( "/{$target_zip}.*$/i", $zip ) ) {
    echo 'matched';
    break;
  }
  else {
    echo 'not matched';
  }
}

Но это совсем не соответствует почтовому индексу. Может кто-нибудь сказать мне, в чем здесь проблема?

Ответы [ 4 ]

0 голосов
/ 13 апреля 2020

Проблема в том, что в l oop шаблон всегда одинаков:

if ( preg_match( "/2347890.*$/i", $zip ) ) {

Я думаю, что вы хотели использовать значение $zip как часть шаблона, который вызывает проблему, повторяющую последний раз git 0+ раз в:

if ( preg_match( "/234*.*$/i", $zip ) ) {
                     ^^

В качестве альтернативы, вы также можете извлечь цифры из $zip_codes, используя группу захвата и соответствуйте необязательному следующему цифры.

$zip_codes = array( '12556', '765547', '234*', '987*', '237' );
$target_zip = '2347890';

foreach($zip_codes as $zip ) {
    $digitsOnly = preg_replace("~^(\d+)\**$~", "$1", $zip);
    if (strpos($target_zip, $digitsOnly) === 0) {
        echo "$zip matched $target_zip" . PHP_EOL;
        break;
    }
    else {
        echo "$zip not matched $target_zip" . PHP_EOL;
    }
}

Выход

12556 not matched 2347890
765547 not matched 2347890
234* matched 2347890

Php демо

0 голосов
/ 13 апреля 2020

Одна из проблем заключается в том, что использование 234* в регулярном выражении будет соответствовать любому числу 4.

Другая проблема заключается в том, что вы подходите до конца (используя $), но не начало, поэтому 789 (с добавленной .*) также будет соответствовать (так как оно в середине). В этом коде я использую ^{$zip}$, с *, замененным на .*, чтобы соответствовать любым конечным символам ...

$zip_codes = array( '12556', '765547', '789', '234', '234*', '987*' );
$target_zip = '2347890';

foreach( $zip_codes as $zip ) {
    $zip = str_replace("*", ".*", $zip);
    if ( preg_match( "/^{$zip}$/i", $target_zip ) ) {
        echo $zip.' matched'.PHP_EOL;
        break;
    }
    else {
        echo $zip.' not matched'.PHP_EOL;
    }
}
0 голосов
/ 13 апреля 2020

Здесь вам не нужно регулярное выражение.

Вы можете искать *, и исходя из этого ищите точное количество символов -1.

$zip_codes = array( '12556', '765547', '234*', '987*' );
$target_zip = '2347890';


foreach($zip_codes as $zip){
    if(strpos($zip, "*") !== false){
      //if "234* -1 = "234"    == substr("2347890",0,3)
        if(substr($zip, 0, -1) == substr($target_zip, 0, strlen($zip)-1)){
            echo "wildcard match";
        }
    }else{
        if($zip == $target_zip){
            echo "excat match";
        }
    }
}

https://3v4l.org/hIGER

0 голосов
/ 13 апреля 2020

Вам необходимо преобразовать значения $zip в правильные регулярные выражения, преобразовав * в .* (или, возможно, \d*); затем вы можете проверить их по $target_zip:

$zip_codes = array( '12556', '765547', '234*', '987*' );
$target_zip = '2347890';

foreach( $zip_codes as $zip ) {
    echo $zip;
    if (preg_match('/' . str_replace('*', '.*', $zip) . '/', $target_zip)) {
        echo ' matched'. PHP_EOL;
        break;
    }
    else {
        echo ' not matched' . PHP_EOL;
    }
}

Вывод:

12556 not matched
765547 not matched
234* matched

Демонстрация на 3v4l.org

У вас нет ' t указывает, хотите ли вы, чтобы значение в $zip_codes соответствовало всему значению $target_zip или только его части. Код выше будет работать только для части (то есть 234 будет соответствовать 12345); если вы этого не хотите, измените конструкцию регулярного выражения на:

if (preg_match('/^' . str_replace('*', '.*', $zip) . '$/', $target_zip)) {

Якоря обеспечат соответствие $zip полному $target_zip.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...