maestroerror/eloquent-regex

Eloquent Regex 为正则表达式带来了简洁和优雅。专为 Laravel 开发者设计,此包提供了一种流畅、直观的接口,用于在您的 PHP 应用程序中构建和执行正则表达式模式。

1.3.1 2024-05-09 14:33 UTC

README

EloquentRegex 为正则表达式带来了简洁和优雅。专为 Laravel 开发者设计,此包提供了一种流畅、直观的接口,用于在您的 PHP 应用程序中构建和执行正则表达式模式。

EloquentRegex::source('test@example.com')->email()->check();

喜欢我们在做的事情吗?请用快速星标表示您的支持!⭐

希望直接在浏览器中拥有相同的功能?请查看 JS 版本:SimplifiedRegex 🚀

被文档压得喘不过气来?通过 ChatGPT Plus 订阅,您可以通过使用EloquentRegex 助手 GPT 来简化您的体验 🤖

目录

概述

梦想着这样一个世界,正则表达式不再像火箭科学一样难? 😄🚀

正则表达式(regex)无疑是强大的。它们是字符串操作和验证的瑞士军刀。但说实话,它们也可能让人头疼。语法密集,一个小错误就可能导致整个操作失败。它们似乎被设计得尽可能令人畏惧,尤其是当你只是想验证一个电子邮件地址时!

请进入 EloquentRegex。我们的目标是使 Laravel 中的正则表达式工作不仅可行,而且真正有趣。是的,你没听错——有趣

EloquentRegex 是一个 PHP/Laravel 包,它提供了一个流畅、直观的界面来构建和执行正则表达式。无论您需要验证用户输入、解析文本还是从字符串中提取特定信息,EloquentRegex 都使这变得简单直接。

例如

$link = 'https://www.example.com/home';
$isValidUrl = EloquentRegex::source($link)->url()->check(); // true

另一个

$isStrong = EloquentRegex::source("StrongP@ssw0rd")->password(function($options) {
    $options->minLength(8)->minUppercase(1)->minNumbers(1)->minSpecialChars(1);
})->check(); // true

还有更多 😄

EloquentRegex::start("#hello #world This is a #test")->hash()->text()->get();
// ['#hello', '#world', '#test']

主要功能🔑

  • 即用型模式:常见的模式,如电子邮件、URL 和 IP 地址,已预先定义并准备好使用。只需几个键入,即可开始验证。
  • 自定义模式变得简单:使用易于使用的流畅界面构建您自己的正则表达式模式。向可读的正则表达式问好!
  • 选项和过滤器:使用选项和过滤器来定制正则表达式操作以进行精确匹配。这就像把正则表达式巫师放在你的指尖。
  • Laravel 集成:无缝集成到您的 Laravel 项目中,利用 Laravel 优雅的语法和功能。

有关包及其内部工作的更多详细信息,请参阅 STRUCTURE.md 文件。

入门🧭

只需通过 Composer 安装该包,您就可以准备好在 PHP/Laravel 应用程序中摆脱正则表达式的痛苦。运行安装命令

composer require maestroerror/eloquent-regex

记住,正则表达式不必成为挫折的来源。有了 EloquentRegex,您将走向成为正则表达式大师的道路,同时编写更干净、更易于维护的 Laravel 代码。

需要快速入门?请阅读 快速入门指南! 🚀

基本用法

EloquentRegex 简化了 Laravel 中的正则表达式,使其易于验证数据、搜索文本和提取信息。本节介绍了 EloquentRegex 的基本用法,包括利用即用型模式和创建自定义模式。

首先,您需要包含 EloquentRegex 类。

use Maestroerror\EloquentRegex\EloquentRegex;

推荐用于 Laravel

use Maestroerror\EloquentRegex\Facades\EloquentRegex;

使用结构非常类似于 Laravel 的 Eloquent ORM,请参阅

[Initiator][Pattern][?Optional][Action]

让我们来分解一下

  • 初始化器设置目标字符串
EloquentRegex::source($yourString);
  • 模式可以是用于一个即用型模式或您自己的自定义模式(我们将在后面讨论自定义模式)。让我们保持示例简单,并添加 URL 模式
EloquentRegex::source($yourString)->url();

注意:大多数 可选 方法是表达式标志,我们将在下一节中讨论它们

  • 操作是执行方法,请参阅示例
// get() will return array/collection of URLs if any found in $yourString
EloquentRegex::source($yourString)->url()->get();

// check() will return true if $yourString exactly matches the pattern
// In this case, if $yourString is URL, false otherwise
EloquentRegex::source($yourString)->url()->check();

// checkString() will return true if $yourString contains any matches of the pattern
// In this case, if $yourString contains minimum 1 URL, false otherwise
EloquentRegex::source($yourString)->url()->checkString();

// count() will return count of matches, in this case, amount of URLs in $yourString
EloquentRegex::source($yourString)->url()->count();

// toRegex() will return string - raw regex pattern (without options applied)
EloquentRegex::source($yourString)->url()->toRegex();

即用型模式📑

EloquentRegex自带一套预定义的通用验证/提取任务模式。这些模式设计得简单易懂,实现起来所需努力最小。

我们有多种方式来应用选项,但最常见和简单的方式是将它们作为参数传递。请注意,所有参数都是可选的。

在这里,您可以查看所有可用的预定义模式及其参数

public function textOrNumbers(
  int $minLength,
  int $maxLength,
  int $minUppercase,
  int $minLowercase,
  int $minNumbers,
  int $maxNumbers
);
// $onlyDomains & $onlyExtensions array
// or string separated by comma `"example.org,example.com"`
public function email(
  int $maxLength,
  array|string $onlyDomains,
  array|string $onlyExtensions
);
public function url(array|string $onlyProtocol);
// $onlyDomains & $onlyExtensions array or string separated by comma "org,com"
public function domainName(
  int $maxLength,
  array|string $onlyDomains,
  array|string $onlyExtensions
);
// Support YYYY-MM-DD, DD-MM-YY and DD-MM-YYYY formats with any date separator ("/", ".", "-")
public function date();
public function time();
public function ipAddress();
public function ipv6Address();
// $cardTypes string separated by comma "visa, amex"
public function creditCardNumber(string $cardTypes);
// $countryCode should passed without "+" sign: phone("1"), phone("995")
public function phone(string $countryCode);
public function username(int $maxLength);
public function password(
  int $minLength,
  int $minUppercase,
  int $minNumbers,
  int $minSpecialChars
);
// $restrictTags & $onlyTags array or string
// separated by comma `"script, style"`.
// It isn't recomended to use both option simultaneously
public function htmlTag(array|string $restrictTags, array|string $onlyTags);
// $specificCurrencies array of currency symbols or string separated by comma "$, ₾"
public function currency(
  int $minDigits,
  int $maxDigits,
  array|string $specificCurrencies
);
// $pathType allowed values: "absolute" & "relative"
public function filePath(
  int $isDirectory,
  bool $isFile,
  bool $fileExists,
  string $pathType
);
public function filePathWin(
  int $isDirectory,
  bool $isFile,
  bool $fileExists
);

这还没有满足您的所有需求?让我们看看自定义模式部分。

自定义模式🛠️

对于预定义模式不足的情况,EloquentRegex允许您使用start或customPattern方法作为启动器来定义自定义模式。

EloquentRegex::start($yourString);
// Or
EloquentRegex::customPattern($yourString);

注意:它们做的完全一样,您可以使用您喜欢的任何一个。

创建自定义模式

您可以从构建一个匹配特定字符串格式的自定义模式开始,例如以字母开头后跟数字的自定义ID格式。

$result = EloquentRegex::start('ID123456')
            ->literal('ID')
            ->digitsRange(1, 10)
            ->check();

if ($result) {
    echo "The string matches the custom ID format!";
} else {
    echo "The string does not match the custom ID format.";
}

注意:如果您只需要构建正则表达式而没有源字符串,可以使用EloquentRegex::builder()->pattern()

自定义模式构建器支持广泛的字符类和所有特殊字符。此外,可以使用literalexact方法来匹配所需的精确字符串,或使用char方法来匹配精确字符。完整的方法列表即将推出。在此之前,您可以查看这些文件。

应用量词#️⃣

正则表达式中的量词是符号或符号集,用于指定字符、分组或字符类必须出现的实例数,才能找到匹配项。EloquentRegex改进了量词的使用方式,使其定义模式出现频率的方式更简单、更直观。

可选元素

要使一个元素可选,请使用'?'。这匹配前一个元素(本例中的'-')零次或一次出现。

// Matches a string that may or may not contain a dash
$result = EloquentRegex::start($yourString)->exact("123")->dash('?')->exact("456")->check();
// Result would be true in both cases of $yourString: "123456" & "123-456"

指定范围

要指定出现次数的范围,请使用由逗号分隔的两个数字的字符串'2,5'。这匹配前一个元素至少和最多指定的次数。

// Matches a string with 2 to 5 spaces
$result = EloquentRegex::start($yourString)->text()->space('2,5')->digits()->check();
// Result: the "someText  234" would return true, but the "someText 234" false

一次或多次

要匹配一个元素的一次或多次出现,请使用'+'、'1+'、'1>'或'oneOrMore'。这确保元素至少出现一次。

// Matches strings with one or more backslashes
$result = EloquentRegex::start("\\\\")->backslash('1+')->check();
// Result: true (if one or more backslashes are found)

零次或多次

'0+'量词匹配前一个元素零次或多次出现。

// Matches strings with zero or more forward slashes
$result = EloquentRegex::start($yourString)->alphanumeric()->dot('0+')->check();
// Result would be true in both cases of $yourString: "test258..." & "test"

精确次数

要匹配精确出现次数,请直接指定数字。

// Matches strings with exactly 2 underscores
$result = EloquentRegex::start($yourString)->digits()->underscore('2')->digits()->check();
// Result would be true in cases $yourString: "1235__158", but "1235___158" and "1235_158" will be false

应用到自定义字符集和分组

您可以将量词应用于自定义字符集和分组,作为回调函数后的第二个参数,匹配特定次数的出现。

// Matches strings with exactly 3 periods or colons
$regex = EloquentRegex::builder()->start()
    ->charSet(function ($pattern) {
        $pattern->period()->colon();
    }, '3')->toRegex();
// Result: ([\.\:]){3}

量词值

特殊字符分组中 - 几乎所有允许带有值量词的方法

  • 零次或多次 = "zeroOrMore""0>""0+""*"
  • 一次或多次 = "oneOrMore""1>""1+""+"
  • 可选(零次或一次) = "optional""?""|"
  • 精确次数 = 2"5"
  • 范围 = "0,5"

示例: ->literal("hello world", false, "1+")

但是字符类有不同的方法,让我们以digits为例。

// By defualt it is set as One or More
EloquentRegex::start($yourString)->digits();

// You can completly remove quantifier by passing 0 as first argument
EloquentRegex::start($yourString)->digits(0);

// You can specify exact amount of digit by passing int
EloquentRegex::start($yourString)->digits(5);

// You can specify range of digits by adding "Range" to the method
EloquentRegex::start($yourString)->digitsRange(1, 5); // Matches from 1 to 5 digits

高级用法

随着你对EloquentRegex基础知识的掌握,你可能需要应对更复杂的字符串操作挑战。本“高级用法”部分旨在将你的技能提升到下一个层次。

无论你是在处理复杂的字符串格式、动态模式需求,还是简单地希望优化正则表达式的性能和清晰度,本部分都将引导你了解EloquentRegex的高级功能。你将学习如何充分利用此包的强大功能,使你的Laravel应用程序的文本处理尽可能高效和有效。

选项⚙️

EloquentRegex提供了一种灵活的系统来应用选项到你的模式中。这些选项可以作为额外的断言来细化模式匹配,或者作为过滤器来选择特定的匹配项。应用选项主要有三种方式:直接作为参数、通过回调和通过关联数组。

直接参数

直接将选项作为参数传递给模式方法,用于简单用例。

EloquentRegex::source("StrongP@ssw0rd")->password(8, 1, 1, 1)->check();

回调

回调提供了最大的灵活性,允许任何选项应用于任何模式。此外,对于复杂的配置,它是推荐的方法,可以使你的代码简单易读。

EloquentRegex::source("StrongP@ssw0rd")->password(function($pattern) {
  $pattern->minLength(8)->minUppercase(1)->minNumbers(1)->minSpecialChars(1);
})->check();

关联数组

选项也可以使用关联数组指定,提供了一种清晰简洁的方法来一次性配置多个选项。

EloquentRegex::source("StrongP@ssw0rd")
->password([
  "minLength" => 8,
  "minUppercase" => 1,
  "minNumbers" => 1,
  "minSpecialChars" => 1,
])->check();

注意:为了简单起见 - 所有选项方法恰好有一个参数

作为额外的断言的选项

选项可以做出额外的断言(在使用checkcheckString方法时),超越基本模式匹配,确保匹配项满足特定标准。

// The "filePath" pattern matches any file path
// While "pathType" option Asserts the file path is an absolute
EloquentRegex::source("/var/www/html/index.php")
  ->filePath(["pathType" => "absolute"])
  ->check();

作为过滤器的选项

在某些情况下(在使用get方法时),选项用于过滤从模式匹配中获得的结果,只允许某些匹配项通过。

$string = "Visa: 4111 1111 1111 1111, MasterCard: 5500 0000 0000 0004, Amex: 3400 000000 00009";
// The "creditCardNumber" pattern matches any credit card number
// While "cardTypes" (#1 argument) option filters and returns only VISA and AMEX accordingly
$cards = EloquentRegex::source($string)->creditCardNumber("visa, amex")->get();

自定义模式中的选项

使用自定义模式是解决特定用例的好方法,但有时你需要为匹配项添加额外的断言或过滤器。虽然end()方法默认是可选的,但如果你需要将选项应用于自定义模式,你应该传递数组或回调到end()方法。

// example of using end() method with config array
EloquentRegex::customPattern("Users: user_123, JohnDoe_99")
  ->alphanumeric()
  ->underscore()
  ->digitsRange(0, 2)
  ->end(["minLength" => 10])
  ->checkString();

// example of using end() method with callback
$check = EloquentRegex::customPattern("Users: user_123, JohnDoe_99")
  ->alphanumeric()
  ->underscore()
  ->digits()
  ->end(function ($p) {
      $p->minLength(10)->maxDigits(2);
  })
  ->checkString();

选项列表

以下是现在所有可用的选项列表。如前所述,可以使用回调或数组将选项应用于任何模式。

虽然这种灵活性允许你精确地定制正则表达式模式,但重要的是要理解,一些选项更具体,而一些则更通用。选择正确的选项取决于你的具体用例。

我将选项按它们背后的类分组,以便更清楚地了解其目的

  • 长度选项
public function minLength(int $minLength);
public function maxLength(int $maxLength);
public function length(int $exactLength);
  • 数字选项
public function minNumbers(int $minDigits);
public function maxNumbers(int $maxDigits);
public function minDigits(int $minDigits);
public function maxDigits(int $maxDigits);
public function numberAmount(int $exactAmountOfDigits);
  • 字符选项
public function onlyChars(array $characters);
public function excludeChars(array $characters);
public function minUppercase(int $minAmount);
public function minLowercase(int $maxAmount);
public function minSpecialChars(int $minAmount);
public function maxSpecialChars(int $maxAmount);
public function noSpecialChars(bool $disable = true);
public function onlyLowercase(bool $only = true);
public function onlyUppercase(bool $only = true);

注意:具有默认值的选项可以在回调中使用时无需参数(如noSpecialChars()),但在使用数组时需要参数(如["noSpecialChars" => true]

  • IPv6选项
public function validIPv6();
  • 文件选项
public function isFile(string|null $extension = null);
public function isDirectory(int $check = 1);
  • 文件存在选项
public function fileExists(bool $check = true);
  • 特定货币选项
public function specificCurrencies(array|string $currencies);
public function onlyUSD($only = true);
public function onlyEUR($only = true);
public function onlyGBP($only = true);
public function onlyGEL($only = true);
  • 路径类型选项
// Allowed values int 1; string "absolute" | int 2; string "relative";
public function pathType(string|int $value = 0);
  • 国家代码选项
public function countryCode(string $code);
  • 空格选项
public function noSpaces(bool $disallow = true);
public function noDoubleSpaces(bool $disallow = true);
public function maxSpaces(int $max);
  • 特定域名选项
public function onlyDomains(array|string $domains);
public function onlyExtensions(array|string $extensions);
  • 协议选项
public function onlyProtocol(string|array $protocol);
public function onlyHttp(bool $only = true);
public function onlyHttps(bool $only = true);
  • 卡类型选项
public function onlyVisa(bool $only = true);
public function onlyMasterCard(bool $only = true);
public function onlyAmex(bool $only = true);
public function cardTypes(string $cardTypes);
  • 仅字母数字选项
public function onlyAlphanumeric(bool $only = true);
  • HTML标签选项
public function onlyTags(array|string $tags);
public function restrictTags(array|string $tags);

正则表达式标志🚩

正则表达式标志是特殊的令牌,它们可以修改正则表达式的行为,使模式匹配更加灵活和强大。在EloquentRegex中,将正则表达式标志应用于你的模式可以启用专门的匹配行为,例如不区分大小写的搜索、多行匹配、单行模式以及Unicode字符的支持。让我们通过示例探索如何应用这些标志。

不区分大小写的匹配

有时,字符串中字母的大小写不应影响匹配。为了实现不区分大小写的匹配,请使用asCaseInsensitive()标志。

// When $string can be "Example@Email.COM", or "EXAMPLE@Email.com", or "example@EMAIL.COM" and etc.
$checkWithFlag = EloquentRegex::source($string)
                ->start()
                ->exact("example")
                ->character("@")
                ->exact("email.com")
                ->end()
                ->asCaseInsensitive()->check();

// With the case-insensitive flag, the match succeeds.
expect($checkWithFlag)->toBeTrue();

多行匹配

多行标志允许开始(^)和结束($)锚点匹配字符串中的行首和行尾,而不是整个字符串。

示例:使用check()方法匹配多行中的日期

$string = "2024-01-30\n2024-02-15\n2024-11-30";
$matches = EloquentRegex::source($string)
            ->start()
            ->digits(4)->dash()
            ->digits(2)->dash()
            ->digits(2)
            ->end() // Here you can apply options
            ->asMultiline()->check();
expect($matches)->toBeTrue();

注意:如果您需要检查字符串是否包含日期,使用checkString()方法就足够了。在这个例子中,我们正在检查每一行是否正好是日期。

单行模式

在单行模式下,点号(.)匹配每个字符,包括换行符,允许模式跨行匹配。

示例:使用check()方法将多行文本作为单行字符串匹配文本

$string = "Check out\n this site:";
$check = EloquentRegex::source($string)
          ->start()->anyChars()->character(":")->end()->asSingleline()
          ->check();
expect($check)->toBeTrue(); // Matches across lines due to the single-line flag.

Unicode字符匹配

当处理包含Unicode字符的文本时,Unicode标志确保字符类(如 \w(单词字符 - wordChars 方法)和 \d(数字 - digits 方法))正确匹配Unicode字符。

示例:匹配带有Unicode字符的文本

$string = "მზადაა #1 ✔️ და #2 ✔️";
$matches = EloquentRegex::source($string)
            ->start()->wordCharsRange(0, 2)->end()->asUnicode()->get();
expect($matches)->toContain('და'); // Matches Unicode characters with the Unicode flag.

高级构建器模式方法

除了字符类和特殊字符方法之外,builderPattern还有更多高级方法,以增加灵活性和使用范围。以下是描述builderPattern高级使用方法的说明。

字符集🗃️

在正则表达式中,字符集是一个基本概念,它允许您定义一个字符集合,用于匹配输入字符串中的单个位置。EloquentRegex提供了一种直观的方法来处理正负字符集,增强了模式的多功能性。

正集合(仅这些字符)

正字符集匹配集合中包含的任何字符。它通过将字符括在方括号[...]中来指定。

示例:匹配特定数量的字符集

// Matches exactly 3 occurrences of periods or colons
EloquentRegex::start(".:.")
->charSet(function ($pattern) {
    $pattern->period()->colon();
}, '3')->check();
// Expected to be true as it matches three instances of either a period or a colon

在这个例子中,字符集[\.\:]被创建来匹配点号 . 或冒号 :(在charSet 字符 顺序 中不 重要)。量词 '3' 应用于集外部,以匹配这些字符中的任何三个。

负集合(除了这些字符之外)

负字符集,表示为[^...],匹配不在括号中列出的任何字符。

示例:匹配特定数量的负字符集

// Matches a string containing 2 to 4 characters that are not digits
EloquentRegex::start("abcd")
->negativeCharSet(function ($pattern) {
    // Here, quantifiers inside the set are interpreted as literal symbols
    // Character classes like "digits", "text", and etc. sets default quantifier (+)
    // Hence, '0' is used to disable automatic quantifier addition
    $pattern->digits(0);
}, '2,4')->check();
// Expected to be true as it matches between 2 to 4 non-digit characters

关于字符类的说明

当使用EloquentRegex处理字符集时,重要的是要记住,量词不允许在集合内部使用,因为它们将被解释为符号。为了在集合中包含字符类(如 "\d" 用于数字)而不对类本身应用量词,应将 0 作为第一个参数传递,其中量词应用是一个选项。这确保字符类按预期包含在集合中,而不产生意外的量词。

更新:现在,0 作为参数是可选的,因为字符类不会在集合内部添加默认的 "+" 量词

分组📦

EloquentRegex简化了创建捕获和非捕获分组的流程,允许您将正则表达式模式组织成逻辑部分,并将量词或断言应用于这些组作为一个整体。

捕获分组

捕获分组用于将模式的一部分分组在一起,并捕获匹配的文本以供以后使用。注意,在使用get时,它返回具有不同结构的数组/集合。

// Matching a date format with capturing the parts as separated groups
$result = EloquentRegex::start("2024-01-30, 2023-02-20")
->group(function($pattern) {
    $pattern->digits(4); // Year
})->dash()
->group(function($pattern) {
    $pattern->digits(2); // Month
})->dash()
->group(function($pattern) {
    $pattern->digits(2); // Day
})->end(["excludeChars" => ["4"]])
->get();

/**
 * After excluding "4" character, it filters out
 * the "2024-01-30" match and returns only "2023-02-20"
 * with it's capture groups, so that you get this array:
 * [
 *     [
 *          "result" => "2023-02-20",
 *          "groups" => [
 *              "2023",
 *              "02",
 *              "20"
 *          ],
 *     ]
 * ]
 */

非捕获分组

非捕获分组逻辑上组织模式,而不单独捕获匹配的文本。

// Reproduces an 'alt' html property pattern fron HSA
$regex = EloquentRegex::start('alt="something"')
    ->exact("alt=")
    ->nonCapturingGroup(function ($pattern) {
        $pattern->doubleQuote()->orPattern(function ($pattern) {
            $pattern->singleQuote();
        });
    })->check(); // True; Regex: alt\=(?:\"|')

带量词的分组

两种分组方法都支持量词作为第二个参数。量词可以按照在应用量词部分中描述的相同逻辑应用。

EloquentRegex::start("345-45, 125-787, 344643")
  ->nonCapturingGroup(function ($pattern) {
    $pattern->digits()->dash()->digits();
  }, '+') // Using "+" to match One Or More of this group
  ->get();
// It returns array: ["345-45", "125-787"]

条件匹配❓

断言组允许基于当前匹配点前后模式的(正)存在或(负)不存在进行条件匹配,而不消耗字符串中的字符,因此断言组内部的内容不会添加到匹配中。下面是示例:

正向前瞻和后瞻断言

示例:使用前瞻断言

只有当数字后面跟着一个'D'时才匹配数字

// Expected to be true as '3' is followed by 'D'
EloquentRegex::start('3D')
->digits()->lookAhead(function($pattern) {
    $pattern->character('D');
})->check();
// While using "get()" method, 'D' doesn't appear in matches

示例:使用后瞻断言

只有当数字前面跟着一个'P'时才匹配数字

// Expected to be true as '3' is preceded by 'P'
EloquentRegex::start('P3')
->negativeLookBehind(function($pattern) {
    $pattern->character('P');
})->digits()->check();
// While using "get()" method, 'P' doesn't appear in matches

负向前瞻和后瞻断言

只有当数字后面不是跟着一个'-'时才匹配数字

// "3A" returns True
$string = "3A";
// "3-" returns False
$string = "3-";
EloquentRegex::start($string)
->digits()->negativeLookAhead(function($pattern) {
    $pattern->character('-');
})->check();
// While using "get()" method, '-' doesn't appear in matches

示例:使用负向后瞻断言

只有当数字前面不是跟着一个'-'时才匹配数字

// "A3" returns True
$string = "A3";
// "-3" returns False
$string = "-3";
EloquentRegex::start($string)
->negativeLookBehind(function($pattern) {
    $pattern->character('-');
})->digits()->check();
// While using "get()" method, '-' doesn't appear in matches

模式交替(或模式)⚖️

有时,你可能遇到需要接受一个或另一个模式的情况。例如,在开发EloquentRegex时,一个关键目标是能够重现HSA中常用的模式。考虑HTML标签内的alt属性,它可以跟在双引号或单引号后面。这个要求转化为正则表达式模式如alt\=(\"|'),表示"alt="后跟任意类型的引号的确切匹配。

要使用EloquentRegex实现这一点,你可以利用orPattern方法

EloquentRegex::builder()->start()
    ->exact("alt=")
    ->group(function ($pattern) {
        $pattern->doubleQuote()
        ->orPattern(function ($pattern) {
            $pattern->singleQuote();
        });
    })->toRegex(); // alt\=(\"|')

在这个示例中,我们使用exact方法精确匹配"alt="。然后我们使用group方法创建一个组,将doubleQuote包含在组中,并在orPattern方法的回调中包含singleQuote。这种方法确保模式匹配"或'。

orPattern方法还接受一个量词作为其第二个参数(在回调之后),应用EloquentRegex其他地方相同的量词逻辑。这个特性增加了另一层灵活性,允许你指定任意模式应该出现多少次。

原始方法🧩

在处理正则表达式时,有时你需要直接将一段原始正则表达式插入到你的模式中。这可能是由于模式的复杂性,或者只是因为你正在集成现有的正则表达式片段。EloquentRegex通过特定的方法来满足这一需求,这些方法可以无缝地将原始正则表达式模式集成到更大的表达式中。

添加原始正则表达式模式

addRawRegex方法允许你直接将任何原始正则表达式插入到你的模式中。这对于集成不需要修改的标准正则表达式片段特别有用。

示例:匹配社会保险号码(SSN)

// Directly adds a raw regex pattern for an SSN
EloquentRegex::start('123-45-6789')
    ->addRawRegex('\d{3}-\d{2}-\d{4}')
    ->check();
// Expected to match an SSN format '123-45-6789', but not '123456789'

此方法简单直接,确保你的EloquentRegex模式可以轻松地适应复杂的要求。

将原始正则表达式包裹在非捕获组中

有时,你可能想将原始正则表达式片段作为更大模式的一部分包含在内,而不捕获其匹配项。addRawNonCapturingGroup方法将提供的原始正则表达式包裹在一个非捕获组中,允许它参与匹配而不影响捕获的组。

示例:添加跟随特定字母的数字

// Wraps digits in a non-capturing group and expects an 'A' immediately after
EloquentRegex::source('123A')
    ->addRawNonCapturingGroup('\d', "oneOrMore")->exact('A')
    ->check();
// Expected to match '123A' but not 'A123'

懒惰量词方法🐌

在正则表达式的世界中,贪婪性指的是量词匹配尽可能多的输入。然而,有一些场景下,你希望你的模式匹配满足模式的最小输入部分,这种行为称为“懒惰”或“非贪婪”。EloquentRegex通过lazy()方法引入了一种简单的方式来应用这一概念。

懒惰方法的工作原理

lazy() 方法修改了模式中跟随其后量词的行为,使它们尽可能少地匹配字符。这在您想要从更大的文本块中提取特定部分而不捕获不必要的部分时非常有用。

示例:从文本中提取“秘密编码”消息

考虑这样一种情况,您需要从更大文本中提取括在花括号内且在特定关键字之前编码的消息。使用贪婪方法可能会导致捕获比预期更多的文本,包括消息之间的文本。lazy() 方法确保仅匹配关键字之后花括号内的内容。

$text = "Normal text {secret: message one} more text {secret: another hidden text} end";
$matches = EloquentRegex::source($text)
    ->lookBehind(function ($pattern) {
        $pattern->openCurlyBrace()->exact('secret: ');
    })
    ->lazy()->anyChars()
    ->lookAhead(function ($pattern) {
        $pattern->closeCurlyBrace();
    })
    ->get();

// Extracts ['message one', 'another hidden text'] as separate matches

在这个例子中,如果没有使用 lazy() 方法,模式可能会贪婪地从第一个 {secret: 匹配到最后一个 },包括所有介于其中的内容作为一个单一匹配(message one} more text {secret: another hidden text)。通过应用 lazy(),模式将匹配每个花括号组内满足模式的最小字符串,从而有效地分隔消息。

何时使用懒惰方法

当处理包括可变长度内容(如字符串或文本块)的模式时,lazy() 方法非常有价值,您旨在提取特定的、有界的段。它在解析嵌入在自由文本中的结构化格式、从模板内容中提取数据或任何需要精确分离更大字符串中多个匹配的场景中特别有用。

通过使量词变得懒惰,EloquentRegex 使您能够编写更精确、更有效的模式,确保您的匹配结果完全符合预期,不多也不少。

测试和调试您的正则表达式模式

制作完美的正则表达式模式是一种需要迭代、测试和调试的艺术。EloquentRegex 提供的工具使这一过程更容易、更直观,让您能够调整您的模式,直到它们精确匹配您所需的内容。为此最有用的方法之一是 toRegex() 方法,它输出原始的正则表达式模式。结合像 Regexr 这样的在线工具,您可以在用户友好的环境中可视化并调试您的模式。

使用“toRegex”方法

toRegex() 方法将您的 EloquentRegex 模式转换为标准正则表达式字符串。这对于调试目的或您需要与他人共享模式但其他人可能没有使用 EloquentRegex 的情况非常有用。

示例:将 EloquentRegex 自定义模式转换为原始正则表达式

$pattern = EloquentRegex::source('your test string here')
    ->start()
    ->wordChars()->whitespace()->digits()
    ->end()
    ->toRegex();

// Now, $pattern contains the raw regex string that you can test or debug further.

注意:toRegex 不返回 Options 中使用的正则表达式模式

使用 Regexr 调试

Regexr 是一个免费的在线工具,允许您实时测试和调试正则表达式模式。它提供了对正则表达式每个部分的详细说明,突出显示文本中的匹配项,并提供正则表达式语法的参考指南。

如何使用 Regexr 进行调试
  1. 转换您的模式:使用 toRegex() 方法将您的 EloquentRegex 模式转换为原始正则表达式字符串。
  2. 打开 Regexr:在您的网络浏览器中转到 https://regexr.com/
  3. 粘贴您的模式:将原始正则表达式字符串粘贴到 Regexr 的“表达式”字段。
  4. 测试您的模式:在“测试字符串”区域输入测试字符串以查看您的模式如何匹配。Regexr 将突出显示匹配项,并在模式不符合预期时提供有用的见解和错误。

注意:对于 get 方法的调试,打开“标志”下拉菜单并标记“全局”

有效调试的技巧

  • 从简单开始:从模式的简化版本开始,并逐步增加复杂性。这有助于隔离问题。
  • 使用描述性测试字符串:包括各种测试字符串,以涵盖您期望模式处理的所有场景,以及边缘情况。
  • 注意细节: 正则表达式模式对每个字符都十分敏感。请仔细检查您的符号,特别是那些在正则表达式中具有特殊意义的符号,如 .*? 等。
  • 迭代和改进: 不要期望第一次就能完全正确。利用测试反馈来迭代地改进您的模式。

测试和调试是确保您的正则表达式模式确实按照您的意图工作的重要步骤。通过利用 toRegex() 方法以及 Regexr 等工具,您可以使这个过程更加可管理和高效,从而在 Laravel 应用程序中实现更准确和可靠的正则表达式实现。

为 EloquentRegex 做贡献

我们欢迎社区的贡献!无论您是在修复错误、添加新功能还是改进文档,您的帮助都将使 EloquentRegex 对所有人来说都变得更好。我们遵循经典的 GitHub 贡献流程。以下是如何参与进来。

注意:查看 STRUCTURE.md 可能有助于您更好地理解该包 👍

入门指南

  1. 分叉仓库: 首先在您的 GitHub 账户上分叉 EloquentRegex 仓库。这将为您创建一个个人副本,以便进行实验。

  2. 克隆您的分叉: 将您的分叉仓库克隆到本地计算机上以开始进行更改。使用以下命令,将 YOUR_USERNAME 替换为您自己的 GitHub 用户名

git clone https://github.com/YOUR_USERNAME/eloquent-regex.git
  1. 设置环境: 确保您有一个可工作的 Laravel 环境来测试您的更改。按照项目 README 中的设置说明开始。

进行更改

  1. 创建新分支: 对于每组更改或新功能,在您的本地仓库中创建一个新分支。这可以使您的工作更有组织,并保持与主代码库的分离。
git checkout -b feature/my-new-feature
  1. 进行更改: 实现您的修复、功能或文档更新。确保您的更改集中且限于当前问题,以便于审查。

  2. 提交更改: 一旦您对工作满意,将更改提交到您的分支。编写清晰、简洁的提交信息,说明所做的更改。

git commit -am "Add a brief description of your changes"
  1. 推送到您的分叉: 将您的分支和更改推送到 GitHub 上的分叉。
git push origin feature/my-new-feature

提交拉取请求

  1. 拉取请求 (PR): 导航到 GitHub 上的原始 EloquentRegex 仓库。您将看到一个“比较 & 拉取请求”选项,针对您的分支。点击它以开始提交 PR 的过程。

  2. 描述您的更改: 在 PR 中提供更改的详细描述。包括任何相关的 issue 号码。解释更改的理由以及它们如何改进 EloquentRegex 将帮助审阅者理解您的贡献。

  3. 提交供审查: 一旦您的 PR 准备就绪并且所有检查都通过,提交它供审查。合并之前至少需要一个项目维护者的审查。对反馈持开放态度,并准备好根据建议进行进一步的调整。

审查和合并

  • 合作: 项目维护者将审查您的 PR。这个过程可能涉及一些来回讨论、额外的提交以及根据反馈更新您的 PR。

  • 合并: 一旦您的 PR 被批准,项目维护者将合并它到主代码库中。恭喜您为 EloquentRegex 做出了贡献!

查看 STRUCTURE.md

有关项目结构和贡献指南的更详细信息,请参阅仓库中的 STRUCTURE.md 文件。它概述了 EloquentRegex 的架构并提供了对命名约定、文件组织和其他最佳实践的见解。

感谢您考虑为 EloquentRegex 做出贡献!您的努力帮助改进了开发人员的工具 ❤️。

支持

支持我们的工作?🌟 您可以通过小额捐赠来帮助我们保持代码流畅。每一份支持都对维护和改进我们的开源贡献大有裨益。点击下面的按钮进行捐赠。感谢您的慷慨!

或使用二维码

致谢

像EloquentRegex这样的项目并非孤立存在。它是各种工具和社区灵感和支持的结晶。我们衷心感谢以下人士:

  • Regexr: 作为创建和调试正则表达式的宝贵工具。其直观的界面和详细的解释使我们能够完善我们的正则表达式。

  • ChatGPT: 在用PEST测试全面覆盖代码库方面提供帮助。ChatGPT的指导和建议也对本文档的创建至关重要。

  • PEST框架: 作为一款极其用户友好且功能强大的测试框架。其优雅的语法和强大的功能使编写测试变得愉快,极大地提高了EloquentRegex的质量。

特别感谢为这些工具和资源做出贡献的每一个人。您的工作不仅帮助了EloquentRegex的开发,还为更广泛的开发者社区提供了工具和知识,让我们都能从中受益。

常见问题解答(FAQ)

什么是EloquentRegex?

EloquentRegex是一个PHP/Laravel包,旨在简化正则表达式的创建和执行。它提供了一个流畅、直观的接口,用于构建自定义正则表达式模式以及利用现成的模式执行常见任务,如电子邮件和URL验证。

如何安装EloquentRegex?

EloquentRegex可以通过Composer安装。在您的Laravel项目目录中运行以下命令:

composer require maestroerror/eloquent-regex

我可以在没有Laravel的情况下使用EloquentRegex吗?

尽管EloquentRegex专为Laravel设计,但核心功能可以通过Maestroerror\EloquentRegex\EloquentRegex对象在任意PHP项目中使用,语法保持不变。

use Maestroerror\EloquentRegex\EloquentRegex;

如何使用现成的模式?

可以通过调用EloquentRegex类上的相应方法来调用现成的模式。例如,要验证电子邮件地址:

$isValid = EloquentRegex::source('test@example.com')->email()->check();

如何创建自定义模式?

可以使用startcustomPattern方法创建自定义模式。然后,您可以链接方法来构建您的模式。

$result = EloquentRegex::start('user_123')
->alphanumeric()
->underscore()
->digits()
->get();

我可以将选项应用到任何模式吗?

是的,可以使用回调函数或关联数组将任何选项应用到任何模式。这允许灵活配置正则表达式模式。此外,直接将参数传递给模式方法也是应用选项的额外、易于使用的方式。

我如何调试我的正则表达式模式?

您可以使用toRegex()方法获取原始正则表达式模式字符串。然后,可以使用像Regexr这样的在线工具进行测试和调试,它提供实时匹配和详细解释。有关更多信息,请参阅测试和调试部分。

我如何为EloquentRegex做出贡献?

欢迎贡献!您可以通过fork GitHub存储库、进行更改并提交拉取请求来做出贡献。请确保您的贡献符合项目的编码标准和指南。

我可以在哪里报告问题或请求功能?

问题和功能请求可以在GitHub仓库的“问题”页面上提交。请尽可能提供详细信息,以便我们高效地理解和处理您的请求。

我如何了解EloquentRegex的最新动态?

要了解最新动态,请关注GitHub仓库的最新更改、发布和讨论。您还可以关注仓库以接收所有项目活动的通知,或关注作者的页面

待办事项
  • 添加新模式的选项

    • 添加containsnotContains选项
    • usernameLength: 设置电子邮件用户名部分的最小和最大长度。
    • dateFormat, timeFormat: 指定日期和时间的格式(例如,MM-DD-YYYY,HH:MM)。
  • 实现命名组的用法:/(?P\d{4})-(?P\d{2})-(?P\d{2})/

  • 创建一些用于调试选项的工具

  • 编写文档

    • 创建快速入门指南并添加到文档中。+
    • 在MD文件中添加builderPattern方法列表并从文档中链接。
    • 在文档中添加选项调试部分
即将推出
  • 实现字符串解析模式,以便使用类似"text(2)-digits()"(或"text:2-digits",或"text|2-digits")的字符串作为模式
  • 实现递归模式创建(使用"RI-321"字符串创建匹配此字符串的模式)
  • 使选项可以从配置或提供者控制(?)
  • 使模式可以从配置或提供者控制(?)
  • 使用preg_match而不是preg_match_all实现first()方法
  • 我应该能够使用BuilderPattern创建新的模式
  • 我应该能够使用BuilderPattern将自定义模式添加到现有模式中