Захват групп в строке с использованием preg_match - PullRequest
2 голосов
/ 19 января 2020

У меня возникли проблемы при разборе текстового файла в codeigniter, для каждой строки в файле мне нужно захватить данные групп ... данные: - прогрессивный номер - оператор - производитель - модель - регистрация - тип

Вот вам пример строк файла

 8  SIRIO S.P.A.                                             BOMBARDIER INC.                                       BD-100-1A10             I-FORZ              STANDARD

 9  ESERCENTE PRIVATO                                        PIAGGIO AERO INDUSTRIES S.P.A.                        P.180 AVANTI II         I-FXRJ              SPECIALE/STANDARD

10  MIGNINI & PETRINI S.P.A.                                 ROBINSON HELICOPTER COMPANY                           R44 II                  I-HIKE              SPECIALE/STANDARD

11  MIGNINI & PETRINI S.P.A.                                 ROBINSON HELICOPTER COMPANY                           R44 II                  I-HIKE              STANDARD

12  BLUE PANORAMA AIRLINES S.P.A.                            THE BOEING COMPANY                                    737-86N                 I-LCFC              STANDARD

Для разбора каждой строки я использую следующий код:

if ($fh = fopen($filePath, 'r')) {
    while (!feof($fh)) {
        $line = trim(fgets($fh));

        if(preg_match('/^(\d{1,})\s+(\w{1,})\s+(\w{1,})\s+(\w{1,})\s+(\w{1,})\s+(\w{1,})$/i', $line, $matches))
       {
             $regs[] = array(
             'Operator'     => $matches[1],
             'Manufacturer' => $matches[2],
             'Model'        => $matches[3],
             'Registration' => $matches[4],
             'Type'         => $matches[5]
             );
             $this->data['error'] = FALSE;
        }
    }
    fclose($fh);
 }

Код выше не работает ... Я думаю, потому что некоторые группы данных состоят из более чем одного слова ... например, "SIRIO SPA". Любой намек, чтобы это исправить? Большое спасибо за любую помощь

1 Ответ

3 голосов
/ 19 января 2020

Вы не должны использовать \w для захвата данных, так как некоторые символы в вашем тексте, такие как &, ., - и /, не являются частью символов слова. Более того, некоторые из них разделены пробелами, поэтому вы должны заменить \w{1,} на \S+(?: \S+)*, что позволит правильно захватить ваш текст в созданные вами группы.

Попробуйте изменить это регулярное выражение, и оно должно работать,

^\s*(\d+)\s+(\S+(?: \S+)*)\s+(\S+(?: \S+)*)\s+(\S+(?: \S+)*)\s+(\S+(?: \S+)*)\s+(\S+(?: \S+)*)$

Проверьте это демо

Объяснение того, что \S+(?: \S+)* делает в приведенном выше регулярном выражении.

  • \S+ - \S противоположно \s, что означает, что он соответствует любому не пробелу (не будет совпадать с пробелом, символом табуляции, новой строкой, вертикальным или горизонтальным пространством и вообще любым пробелом). Следовательно, \S+ соответствует одному или нескольким видимым символам
  • (?: \S+)* - Здесь ?: предназначено только для превращения группы в группу без захвата, и после нее есть пробел и \S+, и все это заключенный в круглые скобки с * квантификатором. Таким образом, это означает совпадение с пробелом, за которым следует один или несколько непробельных символов и все это ноль или более раз при использовании квантификатора *.

Так что \S+(?: \S+) будет соответствовать abc или abc xyz или abc pqr xyz и так далее, но в тот момент, когда появляется более одного пробела, совпадение прекращается, поскольку в регулярном выражении присутствует только один пробел до \S+

Надеюсь, мое объяснение понятно. Если все еще есть сомнения, пожалуйста, не стесняйтесь спрашивать.

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