Php 在正则表达式中使用OR运算符时出现意外结果

Php 在正则表达式中使用OR运算符时出现意外结果,php,regex,Php,Regex,我对正则表达式有个问题。我有一个从文件中读取的文本。文本可以包含一个或多个以逗号分隔的ID。 然后我有一个ID列表,想检查其中一个ID是否与我的文本匹配,所以我尝试使用OR运算符: $idString = '2561,3,261,6,540,33,3105,2085,38,42,1066,49,3377,53,3161,91,356,3179,3695,3184,370,123,3451,124,3710,2188,141,404,1435,160,1443,432,435,440,1721,3

我对正则表达式有个问题。我有一个从文件中读取的文本。文本可以包含一个或多个以逗号分隔的ID。
然后我有一个ID列表,想检查其中一个ID是否与我的文本匹配,所以我尝试使用OR运算符:

$idString = '2561,3,261,6,540,33,3105,2085,38,42,1066,49,3377,53,3161,91,356,3179,3695,3184,370,123,3451,124,3710,2188,141,404,1435,160,1443,432,435,440,1721,3261,2498,205,3282,476,482,3301,486,749,3309,243,3059,759,2046,4,262,785,534,541,3360,34,3106,2086,39,43,50,3378,54,1337,61,1351,3157,3162,360,3696,3185,631,3450,3200,666,1436,673,1444,3748,3262,2499,206,3279,3283,470,477,483,3302,490,755,760,2047,2562,1029,263,23,542,35,3107,2087,40,552,553,1321,47,51,3379,55,1338,3163,361,3697,3186,633,3452,639,143,3223,1445,3749,1450,3263,2500,207,3284,478,484,3303,2559,264,1297,22,543,36,44,57,1339,3389,62,3164,3677,362,3180,634,144,1685,1446,430,700,208,3286,479,1249,485,3306,2558,255,265,524,30,288,46,2095,63,2375,3165,403,1447,3242,696,1724,3557,3304,1770,3066,2563,266,544,2338,555,3131,3166,2204,415,1448,1239,3288,480,3305,754,267,545,3370,2378,3152,3170,648,147,679,1449,2537,753,2546,505,2564,3335,268,535,537,539,546,549,65,69,3167,148,3244,744,3068,2565,269,286,547,292,1334,1340,3659,3168,383,153,1705,3267,3060,2566,270,271,3099,548,1660,398,154,1706,2511,746,3332,2568,272,3148,422,3269,752,768,273,3381,3153,3199,155,468,784,274,3093,325,1657,3319,510,3329,3333,275,1432,2230,441,1722,773,3338,276,3641,2108,491,3339,277,2398,107,3181,2245,757,3346,2100,619,1760,2050,3351,2103,667,19,3372,2534,1064,351,1726,2394,2508,2538,2104,3147,2083,2097,2042,2096,2165,2049,2525,2526,1774,2392,2080,2043,2542,2547,2129,2540,2536,2190,2226,2569,2572,2373,2507';
$idString = str_replace(',', '|', $idString);
$text = '1453,2018';
if (preg_match('/' . $idString . '/', $text)) {
  echo 'yes' . PHP_EOL;
} else {
  echo 'no' . PHP_EOL;
}

我希望没有匹配项,因为在我的查找字符串中找不到ID 1453和2018,但它匹配。我认为这是因为ID 3与1453匹配,但这不适合我的用例。

您可以通过输出匹配项来查看正则表达式匹配的内容,例如:

if (preg_match('/' . $idString . '/', $text, $matches)) {
    echo 'yes' . PHP_EOL;
    print_r($matches);
} else {
    echo 'no' . PHP_EOL;
}
你必须调整你的正则表达式来匹配整个单词。。。例如:

if (preg_match('/\b(' . $idString . ')\b/', $text)) {

或者你可以通过使用explode来避免完全使用正则表达式(推荐,它有点疯狂…)

$idString = '2561,3,261,6,540,33,3105,2085,38,42,1066,49,3377,53,3161,91,356,3179,3695,3184,370,123,3451,124,3710,2188,141,404,1435,160,1443,432,435,440,1721,3261,2498,205,3282,476,482,3301,486,749,3309,243,3059,759,2046,4,262,785,534,541,3360,34,3106,2086,39,43,50,3378,54,1337,61,1351,3157,3162,360,3696,3185,631,3450,3200,666,1436,673,1444,3748,3262,2499,206,3279,3283,470,477,483,3302,490,755,760,2047,2562,1029,263,23,542,35,3107,2087,40,552,553,1321,47,51,3379,55,1338,3163,361,3697,3186,633,3452,639,143,3223,1445,3749,1450,3263,2500,207,3284,478,484,3303,2559,264,1297,22,543,36,44,57,1339,3389,62,3164,3677,362,3180,634,144,1685,1446,430,700,208,3286,479,1249,485,3306,2558,255,265,524,30,288,46,2095,63,2375,3165,403,1447,3242,696,1724,3557,3304,1770,3066,2563,266,544,2338,555,3131,3166,2204,415,1448,1239,3288,480,3305,754,267,545,3370,2378,3152,3170,648,147,679,1449,2537,753,2546,505,2564,3335,268,535,537,539,546,549,65,69,3167,148,3244,744,3068,2565,269,286,547,292,1334,1340,3659,3168,383,153,1705,3267,3060,2566,270,271,3099,548,1660,398,154,1706,2511,746,3332,2568,272,3148,422,3269,752,768,273,3381,3153,3199,155,468,784,274,3093,325,1657,3319,510,3329,3333,275,1432,2230,441,1722,773,3338,276,3641,2108,491,3339,277,2398,107,3181,2245,757,3346,2100,619,1760,2050,3351,2103,667,19,3372,2534,1064,351,1726,2394,2508,2538,2104,3147,2083,2097,2042,2096,2165,2049,2525,2526,1774,2392,2080,2043,2542,2547,2129,2540,2536,2190,2226,2569,2572,2373,2507';
$idStrings = explode(',', $idString);
$values = ['1453', '2018'];

$matchedValue = null;
foreach ($values as $value) {
    if (in_array($value, $idStrings)) {
        $matchedValue = $value;
        break;
    }
}

if ($matchedValue !== null) {
    echo 'yes: ' . $matchedValue;
} else {
    echo 'no';
}

preg\u match
的语法是
($pattern,$text)
。改变它如下,为我工作

<?php

$idString = '2561,3,261,6,540,33,3105,2085,38,42,1066,49,3377,53,3161,91,356,3179,3695,3184,370,123,3451,124,3710,2188,141,404,1435,160,1443,432,435,440,1721,3261,2498,205,3282,476,482,3301,486,749,3309,243,3059,759,2046,4,262,785,534,541,3360,34,3106,2086,39,43,50,3378,54,1337,61,1351,3157,3162,360,3696,3185,631,3450,3200,666,1436,673,1444,3748,3262,2499,206,3279,3283,470,477,483,3302,490,755,760,2047,2562,1029,263,23,542,35,3107,2087,40,552,553,1321,47,51,3379,55,1338,3163,361,3697,3186,633,3452,639,143,3223,1445,3749,1450,3263,2500,207,3284,478,484,3303,2559,264,1297,22,543,36,44,57,1339,3389,62,3164,3677,362,3180,634,144,1685,1446,430,700,208,3286,479,1249,485,3306,2558,255,265,524,30,288,46,2095,63,2375,3165,403,1447,3242,696,1724,3557,3304,1770,3066,2563,266,544,2338,555,3131,3166,2204,415,1448,1239,3288,480,3305,754,267,545,3370,2378,3152,3170,648,147,679,1449,2537,753,2546,505,2564,3335,268,535,537,539,546,549,65,69,3167,148,3244,744,3068,2565,269,286,547,292,1334,1340,3659,3168,383,153,1705,3267,3060,2566,270,271,3099,548,1660,398,154,1706,2511,746,3332,2568,272,3148,422,3269,752,768,273,3381,3153,3199,155,468,784,274,3093,325,1657,3319,510,3329,3333,275,1432,2230,441,1722,773,3338,276,3641,2108,491,3339,277,2398,107,3181,2245,757,3346,2100,619,1760,2050,3351,2103,667,19,3372,2534,1064,351,1726,2394,2508,2538,2104,3147,2083,2097,2042,2096,2165,2049,2525,2526,1774,2392,2080,2043,2542,2547,2129,2540,2536,2190,2226,2569,2572,2373,2507';
$idString = str_replace(',', '|', $idString);
$text = '1453,2018';
if (preg_match('/(' . $text . ')/', $idString)) {
  echo 'yes' . PHP_EOL;
} else {
  echo 'no' . PHP_EOL;
}
?>

使用数组解决这个问题太容易了。如果可以使用正则表达式,就不应该使用它们,但这似乎不是您真正的问题,而是另一个问题的MCVE

您应该使用单词边界
\b
,否则在
1453
中可以找到类似
4
的数字
preg_match()
第三个参数保存分析结果

preg_match('/\b(?:' . $idString . ')\b/', $text, $match)

首先你需要做
'/\b('.$idString')\b/'
,其次我认为使用数组更好。如果你只是将两个字符串都转换为数组,并查看不需要
regex
来完成这么简单的任务,这似乎会更容易
array_intersect(explode(',',$idString),explode(',',$text))
足以获取两个字符串中存在的ID列表。如果您已经将ID作为数字存储在数组中,那么您甚至不需要分解
$idStrings
(即更快、更容易阅读和理解的代码)。对不起,我忘记说的是,这是一个重现问题的示例。稍后我想使用正则表达式进行elasticsearch。因此,非常有必要用regx来解决它。为了解释,您的regexp中有id
53
,因此53包含在匹配的文本
14532018
中。无论如何,使用数组会更有效