Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/283.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 如何在内容处置标题中预先匹配所有三种情况?_Php_Regex_Preg Match - Fatal编程技术网

Php 如何在内容处置标题中预先匹配所有三种情况?

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),但我只是想了解是否可以在单个正则表

我尝试使用以下正则表达式解码内容处置头(来自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\'';
    $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
)