Получить подстроку опции в файле CSV - PullRequest
0 голосов
/ 22 июня 2019

Мне нужно проанализировать CSV-файл, чтобы получить некоторую информацию из каждой строки (код компании, описание компании, страна), я использую preg_match в PHP для анализа файла, но у меня возникли проблемы с некоторыми строками.

Ниже некоторых строк файла csv

"ASTA","Aerospace Technologies of Australia Pty Ltd (Australia)"
"ATAC"," American Tactical Aircraft Consultants (United States)"
"ATEC"," ATEC vos (Czech Republic)"
"ATG","Aviation Technology Group Inc (United States)"
"ATLAS","Atlas Aircraft Corporation of South Africa (Pty) Ltd (South Africa)"
"ATR","GIE Avions de Transport Régional (France/Italy)"
"AUSTER","Auster Aircraft Ltd (United Kingdom)"
"AUSTFLIGHT","Austflight ULA Pty Ltd (Australia)"
"AUSTRALIAN AEROSPACE","Australian Aerospace Pty Ltd (Australia)"
"AUSTRALITE","Australite Inc (United States)"
"AUTOGYRO","AutoGyro Europe GmbH (Germany)"
"AVANTAGE","OOO Samoletstroitelynyi Kompaniya Avantazh (Russia)"
"AVCRAFT","AvCraft Aviation LLC (United States)"
"AVEKO","Aveko sro (Czech Republic)"
"AVIA (1)","Azionari Vercellese Industrie Aeronautiche (Italy)"
"AVIA (2)","Avia-Zavody Jirího Dimitrova (Czech Republic)"

Код PHP preg_match выглядит следующим образом:

preg_match('#^(.+?)\s\((.+?)\)$#',$string,$matches);

Код отлично работает со строками, подобными следующей:

"ASSO AEREI","Asso Aerei Srl (Italy)"

В приведенном выше примере я успешно получаю три данных в массив совпадений ... но со следующей строкой

"ATLAS","Atlas Aircraft Corporation of South Africa (Pty) Ltd (South Africa)"

Я получаю, как Описание компании:

Atlas Aircraft Corporation of South Africa

и как Страна:

Pty) Ltd (South Africa

Вместо них они должны быть:

Atlas Aircraft Corporation of South Africa (Pty) Ltd

и

South Africa

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

"AERFER-AERMACCHI","see AERFER and AERMACCHI"

Я получаю пустой массив описания компании.

Любая помощь, чтобы исправить шаблон регулярного выражения?Большое спасибо за любую помощь

Ответы [ 4 ]

3 голосов
/ 22 июня 2019
$csv = <<<'EOD'
"ASTA","Aerospace Technologies of Australia Pty Ltd (Australia)"
"ATAC"," American Tactical Aircraft Consultants (United States)"
"ATEC"," ATEC vos (Czech Republic)"
"ATG","Aviation Technology Group Inc (United States)"
"ATLAS","Atlas Aircraft Corporation of South Africa (Pty) Ltd (South Africa)"
"ATR","GIE Avions de Transport Régional (France/Italy)"
"AUSTER","Auster Aircraft Ltd (United Kingdom)"
"AUSTFLIGHT","Austflight ULA Pty Ltd (Australia)"
"AUSTRALIAN AEROSPACE","Australian Aerospace Pty Ltd (Australia)"
"AUSTRALITE","Australite Inc (United States)"
"AUTOGYRO","AutoGyro Europe GmbH (Germany)"
"AVANTAGE","OOO Samoletstroitelynyi Kompaniya Avantazh (Russia)"
"AVCRAFT","AvCraft Aviation LLC (United States)"
"AVEKO","Aveko sro (Czech Republic)"
"AVIA (1)","Azionari Vercellese Industrie Aeronautiche (Italy)"
"AVIA (2)","Avia-Zavody Jirího Dimitrova (Czech Republic)"
"AERFER-AERMACCHI","see AERFER and AERMACCHI"
EOD;

$url = 'data:text/plain,' . urlencode($csv);

if ( false !== $handle = fopen($url, "r") ) {
    while ( false !== $data = fgetcsv($handle) ) {
        if ( preg_match('~(\S.*?)(?|\h*\(([^)]*)\)|())\h*$~', $data[1], $m) )
            printf("%-70s\t%s\n", $m[1], $m[2]);

    }
}

демо

Шаблон объяснил:

Две важные вещи из вашего вопроса:

  • страна может быть необязательной
  • описание также может содержать круглые скобки

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

\S в начале только для того, чтобы обрезать часть описания слева. Вот почему шаблон не имеет привязки ^. Один из \h* обрежет его справа (из-за не жадного квантификатора).

О части страны: вместо использования необязательной группы без захвата, такой как (?:\h*\(([^)]*)\))?, я решил использовать группу сброса ветвей (?|... (...) ... | ... (...) ...), чтобы гарантировать, что группа захвата 2 существует, даже если страны нет. В группе такого типа группы захвата имеют одинаковый номер в каждой ветви:

(?|
    \h* \( ([^)]*) \) # the country name is present and captured in group 2
  |   # OR
    () # the capture group 2 contains an empty string
)
1 голос
/ 22 июня 2019

Это регулярное выражение охватило все параметры:

"/^(.*?)(\(([^(]*?)\))?$/"

Я попробовал следующий код:

$matches=array();
$re = "/^(.*?)(\(([^(]*?)\))?$/";
preg_match($re, $string, $matches);
foreach( $matches as $match ){
    echo $match."\n";
}

А при запуске с:

$string = "Atlas Aircraft Corporation of South Africa (Pty) Ltd (South Africa)";

Вывод:

Atlas Aircraft Corporation of South Africa (Pty) Ltd (South Africa)
Atlas Aircraft Corporation of South Africa (Pty) Ltd 
(South Africa)
South Africa

При запуске с

$string = "see AERFER and AERMACCHI"

Вывод:

see AERFER and AERMACCHI
see AERFER and AERMACCHI

Таким образом, вы получите описание компании в $matches[1] и страну в $matches[3]

1 голос
/ 22 июня 2019

Лучше использовать функцию fgetcsv () вместо preg_match.

$file = fopen("contacts.csv","r");
print_r(fgetcsv($file));
fclose($file);

Ссылку на эту функцию можно найти здесь fgetcsv ()

0 голосов
/ 22 июня 2019

Я предполагаю, что это выражение может работать:

(.*)\s*\((.*?)\)|(.*)

, которое собирает наши нужные данные с помощью (), используя

(.*)\s*\((.*?)\)

, а другие без, используя

* 1009.*

Демо

Тест

$re = '/(.*)\s*\((.*?)\)|(.*)/m';
$str = 'Aerospace Technologies of Australia Pty Ltd (Australia)
American Tactical Aircraft Consultants (United States)
ATEC vos (Czech Republic)
Aviation Technology Group Inc (United States)
Atlas Aircraft Corporation of South Africa (Pty) Ltd (South Africa)
GIE Avions de Transport Régional (France/Italy)
Auster Aircraft Ltd (United Kingdom)
Austflight ULA Pty Ltd (Australia)
Australian Aerospace Pty Ltd (Australia)
Australite Inc (United States)
AutoGyro Europe GmbH (Germany)
OOO Samoletstroitelynyi Kompaniya Avantazh (Russia)
AvCraft Aviation LLC (United States)
Aveko sro (Czech Republic)
Azionari Vercellese Industrie Aeronautiche (Italy)
Avia-Zavody Jirího Dimitrova (Czech Republic)
see AERFER and AERMACCHI';

preg_match_all($re, $str, $matches, PREG_SET_ORDER, 0);
var_dump($matches);
...