Regex для анализа строки и захвата строки и числа, разделенных запятыми

Я пытаюсь проанализировать файл с похожими строками:

       John David James (DEM) .  .  .  .  .  .     7,808   10.51
Marvin D. Scott (DEM)  .  .  .  .  .  .     6,548    9.55
Maria "Mary" Williams (DEM)  .  .  .  .     4,551    8.58
Dwayne R. Johnson.  .  .  .  .  .  .  .     4,322    8.22
WRITE-IN.  .  .  .  .  .  .  .  .  .  .       188     .29

Мне нужно захватить название и число в первый столбец. Конечный результат будет

John David James (DEM),7808
Marvin D. Scott (DEM),6548
Maria "Mary" Williams (DEM),4551
Dwayne R. Johnson,4322
WRITE-IN,188

я пробовал

\s*\b(.*)\b(\s*\.\s*.*)(\d+,\d+|\d+)\b
\s*\b(.*)\b(\.|.\s)+\b(\d+,\d+|\d+)\b

Какие-либо предложения?

1

Решение

Этот шаблон захватывает имя, находя последовательность точек после имени.
Затем фиксирует число и запятую в качестве числа.

Затем я создаю новый массив и заменяю запятую ничем.

$str = '       John David James (DEM) .  .  .  .  .  .     7,808   10.51
Marvin D. Scott (DEM)  .  .  .  .  .  .     6,548    9.55
Maria "Mary" Williams (DEM)  .  .  .  .     4,551    8.58
Dwayne R. Johnson.  .  .  .  .  .  .  .     4,322    8.22
WRITE-IN.  .  .  .  .  .  .  .  .  .  .       188     .29';
preg_match_all("/\s*(.*?)\s*\.  \..*?([\d,]+)/", $str, $matches);

foreach($matches[1] as $key => $name){
$new[] = $name . "," . str_replace(",", "", $matches[2][$key]);
}


var_dump($new);

Выход:

array(5) {
[0]=>
string(27) "John David James (DEM),7808"[1]=>
string(26) "Marvin D. Scott (DEM),6548"[2]=>
string(32) "Maria "Mary" Williams (DEM),4551"[3]=>
string(22) "Dwayne R. Johnson,4322"[4]=>
string(12) "WRITE-IN,188"}

https://3v4l.org/SdqoZ

1

Другие решения

Вы можете достичь этого с помощью UNGREEDY regexp.

Здесь, когда мы ловим имя, мы хотим «последовательность любого символа, за которой следует последовательность точек и пробелов». Итак, вот эквивалентное регулярное выражение: (.+)[. ]*,

Но двигатель установлен в жадный режим по умолчанию. Что случится? Первая часть (.+) не остановится ни на первой точке, ни на первой найденной пробел. Зачем? Потому что можно выполнить все регулярные выражения до конца строки, и движок пойдет по этому пути, как в жадном режиме.

То же самое относится ко всему регулярному выражению, которое вы можете увидеть в рабочем коде ниже. Первая группа захвата будет захватывать за пределами поля имени.

Мы должны сказать ему «съесть» менее подходящую часть.

<?php
$lines = '
John David James (DEM) .  .  .  .  .  .     7,808   10.51
Marvin D. Scott (DEM)  .  .  .  .  .  .     6,548    9.55
Maria "Mary" Williams (DEM)  .  .  .  .     4,551    8.58
Dwayne R. Johnson.  .  .  .  .  .  .  .     4,322    8.22
WRITE-IN.  .  .  .  .  .  .  .  .  .  .       188     .29
';
$lines = explode("\n", $lines);

// Here, the U flag sets the ungreedy mode
$pattern = '/^\s*(\S.+\S)[. ]+([0-9]+)(?:,([0-9]+))?\s.*$/U';
echo "<pre>";
foreach ($lines  as $line) {
// Here : - ${1} will capture the name,
//        - ${2} the integer part of the number
//        - ${3} the decimal part
echo preg_replace($pattern, '${1},${2}${3}', $line) . "\n";
}
echo "</pre>";
?>

Результат:

John David James (DEM),7808
Marvin D. Scott (DEM),6548
Maria "Mary" Williams (DEM),4551
Dwayne R. Johnson,4322
WRITE-IN,188
1

Если данные выровнены по столбцам (все столбцы имеют фиксированную ширину), используйте строковые функции, такие как substr:

<?php
$lines = '
John David James (DEM) .  .  .  .  .  .     7,808   10.51
Marvin D. Scott (DEM)  .  .  .  .  .  .     6,548    9.55
Maria "Mary" Williams (DEM)  .  .  .  .     4,551    8.58
Dwayne R. Johnson.  .  .  .  .  .  .  .     4,322    8.22
WRITE-IN.  .  .  .  .  .  .  .  .  .  .       188     .29
';

foreach(preg_split('/(\\r|\\n)+/', $lines) as $line) {
if ($line === '') continue;
$name = substr($line, 0, 46);
$amount = substr($line, 46, 10);
$name = rtrim(ltrim($name), " .");
$amount = (float) str_replace(",", "", $amount);
echo $name . ", " . $amount;
}
1
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector