我在上一个问题中有这个RegEx。问题在于它有时会起作用,有时它并不适用。我尝试在在线模拟器上粘贴它并获得:https://regex101.com/r/I3tnY4/3
该文字来自我使用
阅读的文件的file_get_contents
文件的内容已经完成,但是当我通过RegEx运行它来过滤它时:
$data = file_get_contents($var);
$pat = '/intervals \[\d+\]:\s+\Kxmin = (?P<xmin>\d+(\.\d+)?) \
\s+xmax = (?P<xmax>\d+(\.\d+)?)\s+text = "(?P<text>[^"]*)"/m';
// print_r($data);
preg_match_all($pat, $data, $m);
$result = array_map(function($a){
return array_combine(['xmin', 'xmax', 'text'], $a);
}, array_map(null, $m['xmin'], $m['xmax'], $m['text']));
print_r($result);
它返回一个空数组。起初,它正在工作,但当我添加一个for循环来处理多个文件上传时,它停止了工作。
这也发生在我上传文件后立即处理文件之前。
像这样:
if (move_uploaded_file($_FILES["uploadedfile"]["tmp_name"], $target_file)) {
if (file_exists($target_file)) {
$data = file_get_contents($target_file);
$pat = '/intervals \[\d+\]:\s+\Kxmin = (?P<xmin>\d+(\.\d+)?) \
\s+xmax = (?P<xmax>\d+(\.\d+)?)\s+text = "(?P<text>[^"]*)"/m';
preg_match_all($pat, $data, $m);
$result = array_map(function($a){
return array_combine(['xmin', 'xmax', 'text'], $a);
}, array_map(null, $m['xmin'], $m['xmax'], $m['text']));
print_r($result);
}
}
使用上面的代码,由于$ result数组为空,RegEx也失败了。我想这是因为文件尚未准备好被阅读或其他东西。即使我打印文件的内容,一切都在那里。所以我所做的就是将我的页面重定向到另一个执行RegEx处理的文件,并且令人惊讶的是它在那里工作。
答案 0 :(得分:2)
您的任务似乎更侧重于子字符串提取,而不是验证。因此,您可以使用以下模式大大减小模式的大小,加快执行速度并最大限度地减少输出膨胀:
/xmin = (\S+)\s+xmax = (\S+)\s+text = "([^"]*)/
我做了什么? (有关官方模式细分,请参阅this demo)
interval...
匹配,因为您没有使用它(或更具体地说是[]:
\K
,因为您不需要重启&#34;全字符串匹配 - 你没有使用它。array_map()
和array_combine()
无论如何都要分配这些键名。命名捕获组会导致主要输出数组膨胀,除非您有令人信服的理由使用它们,否则应该避免使用它们。它们导致膨胀的原因是因为当您命名捕获组时,preg_match_all()
将写入重复的子数组元素(命名的元素和索引的元素) - 这意味着必要的数据加倍。虽然,是的,您可以使用命名捕获组,这只是意味着您将更改mapping
进程以从每个子数组中删除所有索引元素([0],[1],[2],[3]
)。\s+
。为了记录,您可以在您的模式中使用空格来提高可读性,但要做到这一点,您需要在模式的末尾包含x
作为标记。 x
模式修饰符将忽略模式中使用的所有空格,因此请注意此效果。(?P<xmax>\d+(\.\d+)?)
替换为(\S+)
。这将删除命名的捕获组和嵌套的捕获组,并提取整个非空白子字符串。如果您想验证此字符串,那么我建议:(\d+(?:\.\d+)?)
这会将嵌套组更改为&#34;非捕获&#34; - 再次减少输出阵列膨胀。"
,因此可以删除。m
模式修饰符。您没有使用任何锚元字符(^
或$
),因此该标志没有用处。preg_match_all()
的第四个参数PREG_SET_ORDER
将以这样的方式构建您的子数组:设置多维数组只需要一个array_map()
。我建议你实施它:
代码:(Demo)
$data='intervals [1]:
xmin = 0
xmax = 13.139997023062838
text = ""
intervals [2]:
xmin = 13.139997023062838
xmax = 14.763036269953904
text = "Cities are like siblings in a large polygamous family."
intervals [3]:
xmin = 14.763036269953904
xmax = 17.01
text = ""';
$pat='/xmin = (\S+)\s+xmax = (\S+)\s+text = "([^"]*)/';
if(preg_match_all($pat,$data,$m,PREG_SET_ORDER)){
$assoc_multidim=array_map(function($a){return array_combine(['xmin','xmax','text'],array_slice($a,1));},$m);
var_export($assoc_multidim);
}else{
echo "substring extraction failed";
}
输出:
array (
0 =>
array (
'xmin' => '0',
'xmax' => '13.139997023062838',
'text' => '',
),
1 =>
array (
'xmin' => '13.139997023062838',
'xmax' => '14.763036269953904',
'text' => 'Cities are like siblings in a large polygamous family.',
),
2 =>
array (
'xmin' => '14.763036269953904',
'xmax' => '17.01',
'text' => '',
),
)
使用命名捕获组的另一种方法如下所示:(Demo)
$pat='/xmin = (?P<xmin>\S+)\s+xmax = (?P<xmax>\S+)\s+text = "(?P<text>[^"]*)/';
if(preg_match_all($pat,$data,$m,PREG_SET_ORDER)){
$assoc_multidim=array_map(function($a){return array_intersect_key($a,['xmin'=>'','xmax'=>'','text'=>'']);},$m);
var_export($assoc_multidim);
}else{
echo "substring extraction failed";
}
...你看,这两种技术都需要一点点清理(除非你的流程要注意不要注意索引的子数组),这就是为什么我喜欢不那么臃肿的数组。
答案 1 :(得分:1)