我正在尝试使用类似于以下内容的行来解析文件:
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
有什么建议吗?
答案 0 :(得分: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 :(得分:1)
您可以使用UNGREEDY正则表达式来实现它。
在这里,当我们捕获名称时,我们希望“任何字符序列后跟点和空格序列”。因此,这里是等效的正则表达式:(.+)[. ]*
。
但是引擎默认设置为贪婪模式。会发生什么?第一部分(.+)
不会停在遇到的第一个点或第一个空格处。为什么?因为可以在行尾执行整个正则表达式,并且引擎将采用此路径,就像在贪婪模式下一样。
您可以在下面的工作代码中看到整个正则表达式。第一个捕获组将捕获名称字段之外的对象。
我们需要告诉他“吃掉”较不匹配的部分。
<?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
答案 2 :(得分: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"
}