Использование регулярных выражений для извлечения переменных из письма в виде простого текста? - PullRequest
1 голос
/ 12 апреля 2010

Я ищу хороший пример использования регулярных выражений в PHP для "обратного инжиниринга" формы письма (с известным форматом, конечно), которая была вставлена ​​в многострочное текстовое поле и отправлена ​​в сценарий для обработки.

Итак, допустим, например, это исходный текстовый ввод (взят из пресс-релиза USDA):

ВАШИНГТОН, 5 апреля 2010 г. - Север Американский бизонный кооператив, Нью-Рокфорд, Н.Д., учреждение отзывается приблизительно 25 000 фунтов всего говяжьи головы, содержащие языки, которые могут не было миндалин полностью удалены, что не соответствует правила, которые требуют удаления миндалин от крупного рогатого скота всех возрастов, Министерство сельского хозяйства США Служба безопасности и инспекции пищевых продуктов (FSIS) объявлено сегодня.

Для ясности поля, которые являются переменными, выделены ниже:

[pr_city =] ВАШИНГТОН , [pr_date =] 5 апреля 2010 г. - [corp_name =] Север Американский бизонный кооператив , [corp_city =] Нью-Рокфорд , [corp_state =] N.D. , учреждение отзывается приблизительно [количество =] 25 000 фунтов из [продукт =] весь говяжьи головы, содержащие языки, которые могут не было миндалин полностью удалено , что не соответствует правила, которые требуют [причина =] удаление миндалин от крупного рогатого скота всех возрастов , Министерство сельского хозяйства США Служба безопасности и инспекции пищевых продуктов (FSIS) объявлено сегодня.

Как я могу эффективно извлечь содержимое

  • pr_city
  • pr_date
  • corp_name
  • corp_city
  • corp_state
  • сумма
  • продукт
  • причина

поля из моего примера?

Любая помощь будет оценена, спасибо.

Ответы [ 3 ]

4 голосов
/ 12 апреля 2010

Хорошо, регулярное выражение, работающее на вашем примере, может выглядеть следующим образом (разрывы строк, введенные для того, чтобы этот зверь читался, необходимо удалить перед использованием):

/^(?P<pr_city>[^,]+), (?P<pr_date>[^-]+) - (?P<corp_name>.*?), a 
(?P<corp_city>[^,]+), (?P<corp_state>[^,]+), establishment is 
recalling approximately (?P<amount>.*?) of (?P<product>.*?), 
which is not compliant with regulations that require (?P<reason>.*?), 
the U\.S\. Department of Agriculture\'s Food Safety and Inspection 
Service \(FSIS\) announced today\.$/

Итак, в PHP вы можете сделать

if (preg_match('/^(?P<pr_city>[^,]+), (?P<pr_date>[^-]+) - (?P<corp_name>.*?), a (?P<corp_city>[^,]+), (?P<corp_state>[^,]+), establishment is recalling approximately (?P<amount>.*?) of (?P<product>.*?), which is not compliant with regulations that require (?P<reason>.*?), the U\.S\. Department of Agriculture\'s Food Safety and Inspection Service \(FSIS\) announced today\.$/', $subject, $regs)) {
    $prcity = $regs['pr_city'];
    $prdate = $regs['pr_date'];
    ... etc.
} else {
    $result = "";
}

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

2 голосов
/ 12 апреля 2010

Если окружающий текст является константой, то что-то вроде этого частичного регулярного выражения может помочь:

preg_match('/^(.*?), (.*?)- (.*?), a (.*?), (.*?), establishment is recalling approximately (.*?), which is not compliant with regulations that require (.*?), the U.S. Department of Agriculture's Food Safety and Inspection Service (FSIS) announced today./', $text, $matches);

$matches[1] = 'WASHINGTON';
$matches[2] = 'April 5, 2010';
$matches[3] = ... etc...

Если окружающий текст изменится, то в итоге вы получите тонну ложных совпадений, без совпадений и т. Д. По сути вам понадобится ИИ для анализа / понимания PR-релизов.

1 голос
/ 12 апреля 2010

Редактировать: Пожалуйста, не обращайте внимания на этот сумасшедший ответ, так как два других лучше. Я, вероятно, должен удалить его, но я держу его для справки.

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

preg_replace('([^,]*), ([^-]*)- ...etc...', '<pr_city>\1</pr_city><pr_date>\2</pr_date> ...etc...');

Последующий анализ XML - это излишне сложный процесс, который лучше оставить в документации PHP: http://www.php.net/manual/en/function.xml-parse.php.

Вы можете также рассмотреть преобразование этого файла в JSON с помощью этого метода, а затем использовать json_decode () для его анализа. В любом случае вам нужно подумать о том, что происходит, когда на входе появляются " метки и > символы.

Может быть проще просто сопоставить и удалить один фрагмент текста за раз.

...