Разобрать выражение, используя preg_match - PullRequest
1 голос
/ 04 января 2011

Я пытаюсь разобрать следующее с помощью preg_match:

2020|9 digits number|date hour|word|word

Например:

2020|123456789|01/04/2011 09:09:37|Basketball|sms

Я делаю:

$regex  = '2020|/[0-9]+\|[a-zA-Z]+\|[0-9]{2}\/[0-9]{2}\/[0-9]{4}.*/';
return !(preg_match($regex,$value));

Но я получаю ошибку Delimiter must not be alphanumeric or backslash, и я даже близко не подхожу к ней.

Не могли бы вы мне помочь?

Ответы [ 3 ]

7 голосов
/ 04 января 2011

Если | является вашим разделителем, а данные всегда структурированы так, как вы описываете, почему бы не использовать explode() вместо этого?

$array = explode ("|", $value);
echo $array[0]; // Will output "2020"
echo $array[1]; // Will output "123456789"

Чтобы это работало надежно, ни один из столбцов не долженсодержать "|"в качестве контента персонажа.Но у вас будет и это ограничение с регулярным выражением.

Если вы анализируете целые файлы, созданные следующим образом, взгляните на fgetcsv().

3 голосов
/ 04 января 2011

У вашего регулярного выражения есть несколько проблем

  • Первый побег |.
  • Переместите первый / в начало регулярного выражения. / - это разделитель, обозначающий начало и конец регулярного выражения.
  • Удалите [a-zA-Z]+, поскольку оно совпадает со словом, в котором ваше определение не имеет его.

Это должно работать:

$regex  = '/2020\|[0-9]+\|[0-9]{2}\/[0-9]{2}\/[0-9]{4}.*/';
return !(preg_match($regex,$value));

Вы также можете использовать # в качестве разделителя, чтобы избежать необходимости избегать буквальных символов / s.

$regex  = '#2020\|[0-9]+\|[0-9]{2}/[0-9]{2}/[0-9]{4}.*#';

Это также не так строго, как ваше определение того, как должна выглядеть строка. Я предлагаю сделать следующие улучшения:

  • Совпадение ровно 9 цифр, а не 1+, используя [0-9]{9}.
  • Соответствует метке времени с [0-9]{2}:[0-9]{2}:[0-9]{2}.
  • Сопоставьте последние два слова с \w+\|\w+.
  • Добавьте ^ и $ якоря для принудительного совпадения полной строки.

Все это вместе дает нам:

$regex  = '#^2020\|[0-9]{9}\|[0-9]{2}/[0-9]{2}/[0-9]{4}\s[0-9]{2}:[0-9]{2}:[0-9]{2}\|\w+\|\w+$#';

Смотри на рублевом .

1 голос
/ 04 января 2011

Perl-совместимые регулярные выражения должны начинаться и заканчиваться разделителем (ниже %).Ваш RE начинается с "2", который PCRE интерпретирует как разделитель, следовательно, ошибка "Разделитель не должна быть буквенно-цифровой или обратной косой черты".

Выражение, с которого я бы начал проверять "2020 | 9-значный номер |дата час | слово | слово "равно %^2020\|\d{9}\|\d{2}[-/]\d{2}[-/]\d{4} \d{2}:\d{2}:\d{2}\|\w+\|\w+$%.Кроме даты, RE, соответствующие полям, очень просты: предопределенный класс (\d для цифр, эквивалентный [0-9]; \w для слов, эквивалентный [A-Za-z0-9_]) и повторение ({n} означаетточно n , + означает 1 или более).

Дата соответствует \d{2}[-/]\d{2}[-/]\d{4} \d{2}:\d{2}:\d{2}.При этом используются те же элементы, что и у других подшаблонов, просто их больше.Если вы хотите соответствовать большему количеству форматов даты, вам нужно либо написать более сложное RE, либо извлечь дату и использовать (например) strtotime для ее анализа.

Если вы хотите проанализировать целоеСтрока, а не просто проверить его, следуйте совету Пекки.

...