我目前正在编写一个 PHP 函数,它应该可以帮助我从给定的自述文件文本中提取升级通知。
这是我的源文本:
Some stuff before this notice like a changelog with versioning and explanation text.
== Upgrade Notice ==
= 1.3.0 =
When using Master Pro, 1.3.0 is the new minimal required version!
= 1.1.0 =
When using Master Pro, 1.1.0 is the new minimal required version!
= 1.0.0 =
No upgrade - just install :)
[See changelog for all versions](https://plugins.svn.wordpress.org/master-pro/trunk/CHANGELOG.md).
这是功能:
/**
* Parse update notice from readme file
*
* @param string $content
* @param string $new_version
*
* @return void
*/
private function parse_update_notice( string $content, string $new_version ) {
$regexp = '~==\s*Upgrade Notice\s*==\s*(.*?=+\s*' . preg_quote( $new_version ) . '\s*=+\s*(.*?)(?=^=+\s*\d+\.\d+\.\d+\s*=+|$))~ms';
if ( preg_match( $regexp, $content, $matches ) ) {
$version = trim( $matches[1] );
$notices = (array) preg_split( '~[\r\n]+~', trim( $matches[2] ) );
error_log( $version );
error_log( print_r( $notices, true ) );
}
}
我目前陷入了我的正则表达式。我并没有真正让它发挥作用。这是我最初的想法:
== Upgrade Notice ==
$new_version
= x.x.x =
之间的匹配版本作为匹配 1,例如1.1.0
您不需要使用正则表达式完成所有操作。只需使用正则表达式进行版本检测。这是一个简化版本:
$versions = [];
$currentVersion = '';
$ignore = true;
foreach(explode("\n", $md) as $line) {
if (str_starts_with($line, '== Upgrade Notice ==')) {
$ignore = false;
continue;
}
if (preg_match('/^= ([0-9.]+) =/', $line, $matches)) {
$currentVersion = $matches[1];
continue;
}
if (true === $ignore || '' === $currentVersion) {
continue;
}
$versions[$currentVersion][] = $line;
}
这是一个不基于正则表达式但很好的旧解决方案
strpos()
:
function getNotice($readme, $version)
{
$txt = str_replace("\r", '', $readme);
$p1 = strpos($txt, "== Upgrade Notice ==");
if($p1 !== false)
{
$ver = "= $version =";
$p2 = strpos($txt, $ver, $p1);
if($p2 !== false)
{
$p2 += strlen($ver) + 2;
$p3 = strpos($txt, "\n\n", $p2);
if($p3 !== false)
return substr($txt, $p2, $p3 - $p2);
else
return substr($txt, $p2);
}
}
return '';
}
$readme = <<<README
Some stuff before this notice which is not relevant.
== Upgrade Notice ==
= 1.3.0 =
When using Master Pro, 1.3.0 is the new minimal required version!
Additional line.
= 1.1.0 =
When using Master Pro, 1.1.0 is the new minimal required version!
= 1.0.0 =
No upgrade - just install :)
[See changelog for all versions](https://plugins.svn.wordpress.org/master-pro/trunk/CHANGELOG.md).
README;
echo getNotice($readme, '1.3.0');
输出:
When using Master Pro, 1.3.0 is the new minimal required version!
Additional line.
看来这只是括号位置的错误:
'~==\s*Upgrade Notice\s*==\s*.*?=+\s*(' . preg_quote( $new_version ) .
')\s*=+\s*(.*?)(?=^=+\s*\d+\.\d+\.\d+\s*=+|^\s*?$)~ms'
要获取“升级通知”之后的第一部分,仅匹配第一个后续块与非空行,您可以省略
s
标志以使点匹配换行符并捕获匹配所有包含至少一个单个的后续行非空白字符。
^==\h*Upgrade Notice\h*==\R\s*^=\h*(1\.3\.0)\h*=\R\s*^((?:\h*\S.*(?:\R\h*\S.*)*)+)
PHP 中的行:
$regexp = '~^==\h*Upgrade Notice\h*==\R\s*^=\h*(' . preg_quote( $new_version ) . ')\h*=\R\s*^((?:\h*\S.*(?:\R\h*\S.*)*)+)~m';
如果您希望能够确定匹配“升级通知”后出现的次数,可以使用量词来跳过以版本模式开头的出现次数:
^==\h*Upgrade Notice\h*==(?:(?:\R(?!=\h*\d+\.\d+\.\d+\h*=$).*)*\R=\h*(\d+\.\d+\.\d+)\h*=$\s*){2}(^\h*\S.*(?:\R\h*\S.*)+)
^
字符串开头==\h*Upgrade Notice\h*==
起始模式,其中 \h*
匹配可选的水平空白字符(?:
非捕获组
(?:\R(?!=\h*\d+\.\d+\.\d+\h*=$).*)*
匹配所有不以版本模式开头的行\R=\h*
匹配换行符和 =
后跟水平空白字符(\d+\.\d+\.\d+)
捕获组1,匹配版本\h*=$\s*
匹配水平空白字符,=
并断言字符串结尾并匹配可选空白字符){2}
使用量词(在本例中为{2}
)来匹配 n 次版本模式^
字符串开头(
捕获第 2 组
(?:\h*\S.*(?:\R\h*\S.*)*)+
匹配至少包含一个非空白字符的 1 行或多行)
关闭群组