composer/pcre
Composer 安装命令:
composer require composer/pcre
包简介
PCRE wrapping library that offers type-safe preg_* replacements.
README 文档
README
PCRE wrapping library that offers type-safe preg_* replacements.
This library gives you a way to ensure preg_* functions do not fail silently, returning
unexpected nulls that may not be handled.
As of 3.0 this library enforces PREG_UNMATCHED_AS_NULL usage
for all matching and replaceCallback functions, read more below
to understand the implications.
It thus makes it easier to work with static analysis tools like PHPStan or Psalm as it
simplifies and reduces the possible return values from all the preg_* functions which
are quite packed with edge cases. As of v2.2.0 / v3.2.0 the library also comes with a
PHPStan extension for parsing regular expressions and giving you even better output types.
This library is a thin wrapper around preg_* functions with some limitations.
If you are looking for a richer API to handle regular expressions have a look at
rawr/t-regx instead.
Installation
Install the latest version with:
$ composer require composer/pcre
Requirements
- PHP 7.4.0 is required for 3.x versions
- PHP 7.2.0 is required for 2.x versions
- PHP 5.3.2 is required for 1.x versions
Basic usage
Instead of:
if (preg_match('{fo+}', $string, $matches)) { ... } if (preg_match('{fo+}', $string, $matches, PREG_OFFSET_CAPTURE)) { ... } if (preg_match_all('{fo+}', $string, $matches)) { ... } $newString = preg_replace('{fo+}', 'bar', $string); $newString = preg_replace_callback('{fo+}', function ($match) { return strtoupper($match[0]); }, $string); $newString = preg_replace_callback_array(['{fo+}' => fn ($match) => strtoupper($match[0])], $string); $filtered = preg_grep('{[a-z]}', $elements); $array = preg_split('{[a-z]+}', $string);
You can now call these on the Preg class:
use Composer\Pcre\Preg; if (Preg::match('{fo+}', $string, $matches)) { ... } if (Preg::matchWithOffsets('{fo+}', $string, $matches)) { ... } if (Preg::matchAll('{fo+}', $string, $matches)) { ... } $newString = Preg::replace('{fo+}', 'bar', $string); $newString = Preg::replaceCallback('{fo+}', function ($match) { return strtoupper($match[0]); }, $string); $newString = Preg::replaceCallbackArray(['{fo+}' => fn ($match) => strtoupper($match[0])], $string); $filtered = Preg::grep('{[a-z]}', $elements); $array = Preg::split('{[a-z]+}', $string);
The main difference is if anything fails to match/replace/.., it will throw a Composer\Pcre\PcreException
instead of returning null (or false in some cases), so you can now use the return values safely relying on
the fact that they can only be strings (for replace), ints (for match) or arrays (for grep/split).
Additionally the Preg class provides match methods that return bool rather than int, for stricter type safety
when the number of pattern matches is not useful:
use Composer\Pcre\Preg; if (Preg::isMatch('{fo+}', $string, $matches)) // bool if (Preg::isMatchAll('{fo+}', $string, $matches)) // bool
Finally the Preg class provides a few *StrictGroups method variants that ensure match groups
are always present and thus non-nullable, making it easier to write type-safe code:
use Composer\Pcre\Preg; // $matches is guaranteed to be an array of strings, if a subpattern does not match and produces a null it will throw if (Preg::matchStrictGroups('{fo+}', $string, $matches)) if (Preg::matchAllStrictGroups('{fo+}', $string, $matches))
Note: This is generally safe to use as long as you do not have optional subpatterns (i.e. (something)?
or (something)* or branches with a | that result in some groups not being matched at all).
A subpattern that can match an empty string like (.*) is not optional, it will be present as an
empty string in the matches. A non-matching subpattern, even if optional like (?:foo)? will anyway not be present in
matches so it is also not a problem to use these with *StrictGroups methods.
If you would prefer a slightly more verbose usage, replacing by-ref arguments by result objects, you can use the Regex class:
use Composer\Pcre\Regex; // this is useful when you are just interested in knowing if something matched // as it returns a bool instead of int(1/0) for match $bool = Regex::isMatch('{fo+}', $string); $result = Regex::match('{fo+}', $string); if ($result->matched) { something($result->matches); } $result = Regex::matchWithOffsets('{fo+}', $string); if ($result->matched) { something($result->matches); } $result = Regex::matchAll('{fo+}', $string); if ($result->matched && $result->count > 3) { something($result->matches); } $newString = Regex::replace('{fo+}', 'bar', $string)->result; $newString = Regex::replaceCallback('{fo+}', function ($match) { return strtoupper($match[0]); }, $string)->result; $newString = Regex::replaceCallbackArray(['{fo+}' => fn ($match) => strtoupper($match[0])], $string)->result;
Note that preg_grep and preg_split are only callable via the Preg class as they do not have
complex return types warranting a specific result object.
See the MatchResult, MatchWithOffsetsResult, MatchAllResult, MatchAllWithOffsetsResult, and ReplaceResult class sources for more details.
Restrictions / Limitations
Due to type safety requirements a few restrictions are in place.
- matching using
PREG_OFFSET_CAPTUREis made available viamatchWithOffsetsandmatchAllWithOffsets. You cannot pass the flag tomatch/matchAll. Preg::splitwill also rejectPREG_SPLIT_OFFSET_CAPTUREand you should usesplitWithOffsetsinstead.matchAllrejectsPREG_SET_ORDERas it also changes the shape of the returned matches. There is no alternative provided as you can fairly easily code around it.preg_filteris not supported as it has a rather crazy API, most likely you should rather usePreg::grepin combination with some loop andPreg::replace.replace,replaceCallbackandreplaceCallbackArraydo not support an array$subject, only simple strings.- As of 2.0, the library always uses
PREG_UNMATCHED_AS_NULLfor matching, which offers much saner/more predictable results. As of 3.0 the flag is also set forreplaceCallbackandreplaceCallbackArray.
PREG_UNMATCHED_AS_NULL
As of 2.0, this library always uses PREG_UNMATCHED_AS_NULL for all match* and isMatch*
functions. As of 3.0 it is also done for replaceCallback and replaceCallbackArray.
This means your matches will always contain all matching groups, either as null if unmatched or as string if it matched.
The advantages in clarity and predictability are clearer if you compare the two outputs of running this with and without PREG_UNMATCHED_AS_NULL in $flags:
preg_match('/(a)(b)*(c)(d)*/', 'ac', $matches, $flags);
| no flag | PREG_UNMATCHED_AS_NULL |
|---|---|
| array (size=4) | array (size=5) |
| 0 => string 'ac' (length=2) | 0 => string 'ac' (length=2) |
| 1 => string 'a' (length=1) | 1 => string 'a' (length=1) |
| 2 => string '' (length=0) | 2 => null |
| 3 => string 'c' (length=1) | 3 => string 'c' (length=1) |
| 4 => null | |
group 2 (any unmatched group preceding one that matched) is set to ''. You cannot tell if it matched an empty string or did not match at all |
group 2 is null when unmatched and a string if it matched, easy to check for |
group 4 (any optional group without a matching one following) is missing altogether. So you have to check with isset(), but really you want isset($m[4]) && $m[4] !== '' for safety unless you are very careful to check that a non-optional group follows it |
group 4 is always set, and null in this case as there was no match, easy to check for with $m[4] !== null |
PHPStan Extension
To use the PHPStan extension if you do not use phpstan/extension-installer you can include vendor/composer/pcre/extension.neon in your PHPStan config.
The extension provides much better type information for $matches as well as regex validation where possible.
License
composer/pcre is licensed under the MIT License, see the LICENSE file for details.
composer/pcre 适用场景与选型建议
composer/pcre 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 347.8M 次下载、GitHub Stars 达 702, 最近一次更新时间为 2021 年 11 月 30 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「regex」 「PCRE」 「regular expression」 「preg」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 composer/pcre 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 composer/pcre 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 composer/pcre 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
Regex is library containing lightweight wrappers around regular expression libraries and extensions for day to day use.
Advanced TYPO3 redirect management for sys_redirect with regex and host/language-aware matching, CSV/.htaccess import/export, categories and priority, automatic slug redirect workflows, plus hit/log analytics.
Adds PHP PCRE preg functions as Twig filters.
Adds PHP's preg_replace function as a Twig filter.
Convert Regular Expressions into text, for testing
Fluent regular expressions in PHP.
统计信息
- 总下载量: 347.8M
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 703
- 点击次数: 30
- 依赖项目数: 40
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2021-11-30