регулярное выражение, совпадающее с несколькими значениями, когда они могут не существовать - PullRequest
0 голосов
/ 17 августа 2010

Я пытаюсь настроить preg_match_all, чтобы он соответствовал дистанции скачек.

Мой источник перечисляет расы как: xmxfxy Я хочу сопоставить значение m, значение f, значение y. Однако у разных рас может быть только m, или f, или y, или две из них, или даже все три.

// e.g. $raw = 5f213y;

preg_match_all('/(\d{1,})m|(\d{1,})f|(\d{1,})y/', $raw, $distance);

Вышеупомянутый вид работает, но по какой-то причине совпадения появляются в непредсказуемых позициях в возвращенном массиве Я думаю, это потому, что он запускает матч 3 раза для каждого ИЛИ. Как мне сопоставить все три (которые могут существовать или не существовать) в одном прогоне.

EDIT Полная строка образца:

Hardings Catering Services Handicap (Div I) Cl6 5f213y

Ответы [ 3 ]

1 голос
/ 18 августа 2010

Если я вас правильно понимаю, вы обрабатываете списки (например, те, что у вас в вопросе) по одному. В этом случае вы должны использовать preg_match, а не preg_match_all, и регулярное выражение должно соответствовать всему коду «расстояния», а не отдельным его компонентам. Попробуйте это:

preg_match('#\b(?:(?<M>\d+)m|(?<F>\d+)f|(?<Y>\d+)y){1,3}\b#',
           $raw, $distance);

Результаты теперь хранятся в одномерном массиве, но вам все равно не нужно беспокоиться о номерах групп; вместо этого вы можете получить к ним доступ по имени (например, $distance['M'], $distance['F'], $distance['Y']).

Обратите внимание, что хотя это регулярное выражение сопоставляет коды с одним, двумя или тремя компонентами, буквы не должны быть уникальными. Ничто не мешает ему сопоставить что-то вроде 1m2m3m (кстати, слабость, свойственная вашему собственному подходу).

0 голосов
/ 18 августа 2010

Если я правильно понимаю, что вы спрашиваете правильно, вы хотели бы получить каждое число из этих значений отдельно? Это работает для меня:

$input = "Hardings Catering Services Handicap (Div I) Cl6 5f213y";

preg_match_all('/((\d+)(m|f|y))/', $input, $matches);

После выполнения preg_match_all(), $matches[2] содержит массив совпадающих чисел (в этом случае $matches[2][0] равно 5, а $matches[2][1] равно 213.

Если существуют все три значения, m будет в $matches[2][0], f в $matches[2][1] и y в $matches[2][2]. Если какие-либо значения отсутствуют, следующее значение будет увеличено. Также может пригодиться, что $matches[3] будет содержать массив соответствующей совпавшей буквы, поэтому, если вам нужно проверить, было ли это m, f или y, вы можете.

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

0 голосов
/ 17 августа 2010

вы можете использовать "?" как условный

preg_match_all('/((\d{1,})m)?|((\d{1,})f)?|((\d{1,})y)?/', $raw, $distance);
...