Php 如何在内容处置标题中预先匹配所有三种情况?
我尝试使用以下正则表达式解码内容处置头(来自curl)以获取文件名:Php 如何在内容处置标题中预先匹配所有三种情况?,php,regex,preg-match,Php,Regex,Preg Match,我尝试使用以下正则表达式解码内容处置头(来自curl)以获取文件名: <?php $str = 'attachment;filename="unnamed.jpg";filename*=UTF-8\'\'unnamed.jpg\''; preg_match('/^.*?filename=(["\'])([^"\']+)\1/m', $str, $matches); print_r($matches); 现在我正在使用两个正则表达式(带if-else),但我只是想了解是否可以在单个正则表
<?php
$str = 'attachment;filename="unnamed.jpg";filename*=UTF-8\'\'unnamed.jpg\'';
preg_match('/^.*?filename=(["\'])([^"\']+)\1/m', $str, $matches);
print_r($matches);
现在我正在使用两个正则表达式(带if-else),但我只是想了解是否可以在单个正则表达式中执行?只是为了让我自己学习掌握正则表达式。一种方法是在单个正则表达式中使用交替选项,以匹配单引号/双引号文件名或完全不带引号的文件名。注意,这种方法的一个副作用是我们在正则表达式中引入了更多的捕获组。所以我们需要一些额外的逻辑来处理这个问题
<?php
$str = 'attachment;filename=unnamed.jpg;filename*=UTF-8\'\'unnamed.jpg\'';
$result = preg_match('/^.*?filename=(?:(?:(["\'])([^"\']+)\1)|([^"\';]+))/m',
$str, $matches);
print_r($matches);
$index = count($matches) == 3 ? 2 : 3;
if ($result) {
echo $matches[$index];
}
else {
echo "filename not found";
}
?>
您可以将捕获组设置为可选的
([“\”)?
和\1?
如下:
并在非捕获组中的正则表达式末尾添加分号或字符串结尾,以检查是否存在;
或行的结尾(?:;|$)
您还可以使用\K
重置报告匹配的起点,然后进行匹配,直到遇到双引号或分号[^”]+
。这将只返回文件名
我将使用分支重置功能(?|…|…|…|…)
,该功能提供更可读的模式,并避免为引号创建捕获组。在分支重置组中,每个捕获组对每个备选方案具有相同的编号:
if ( preg_match('~filename=(?|"([^"]*)"|\'([^\']*)\'|([^;]*))~', $str, $match) )
echo $match[1], PHP_EOL;
无论成功的替代方案是什么,捕获总是在组1中。只需输入我的两分钱-您可以使用条件正则表达式:
分解后,这表示:
filename= # match filename=
(['"])? # capture " or ' into group 1, optional
(?(1) # if group 1 was set ...
(.+?)\1 # ... then match up to \1
| # else
([^;]+) # not a semicolon
)
之后,您需要检查第2组或第3组是否在场。或者,使用(经常被忽略的)分支重置来获取@Casimir的答案 看
foreach ($strings as $string) {
preg_match('/^.*?filename="?\K[^";]+/m', $string, $matches);
print_r($matches);
}
if ( preg_match('~filename=(?|"([^"]*)"|\'([^\']*)\'|([^;]*))~', $str, $match) )
echo $match[1], PHP_EOL;
filename=(['"])?(?(1)(.+?)\1|([^;]+))
filename= # match filename=
(['"])? # capture " or ' into group 1, optional
(?(1) # if group 1 was set ...
(.+?)\1 # ... then match up to \1
| # else
([^;]+) # not a semicolon
)