PHP preg_replace 多条规则

发布于 2024-09-13 18:59:26 字数 1535 浏览 2 评论 0原文

我只是想知道如何为 preg_replace 应用多个规则,而不在第一次运行时执行它们。它有点复杂,让我根据一个例子来解释一下。

输入:

$string = 'The quick brown fox jumps over the lazy freaky dog'; 

规则:

  • aio 替换为 u (如果不在单词开头且不在元音之前/之后)
  • eu 替换为 i (如果不在单词开头且不在元音之前/之后)
  • ea 替换为 i (如果不在单词开头)
  • 替换整个单词 ie 狐狸(不应用上述规则)

输出: 这只快速的棕狼在这只活泼活泼的猫身上




我从类似的事情开始:(感谢 Ezequiel Muns 编辑

$patterns = array();
$replacements = array();

$patterns[] = "/(?<!\b|[aeiou])[aio](?![aeiou])/";
$replacements[] = "u";

$patterns[] = "/(?<!\b|[aeiou])[eu](?![aeiou])/";
$replacements[] = "i";

$patterns[] = '/ea/';
$replacements[1] = 'i';

$patterns[] = '/dog/';
$replacements[0] = 'cat';

echo preg_replace($patterns, $replacements, $string);

输出:

Thi qiick briwn fix jimps ivir thi lizy friiky dig



编辑:

如您所见,问题是每条规则都会被前一条规则覆盖

示例 'fox':

  1. 规则:将 fox 变为 fux
  2. 规则:将 fux 变为 fix

有办法避免以下规则?

这有道理吗?

I'm just wondering how to apply several rules for a preg_replace without executing them in the first run. Its a bit complicated let me explain based on an example.

Input:

$string = 'The quick brown fox jumps over the lazy freaky dog'; 

Rules:

  • Replace a, i, o with u (if not at the beginning of a word & if not before/after a vowel)
  • Replace e, u with i (if not at the beginning of a word & if not before/after a vowel)
  • Replace ea with i (if not at beginning of a word)
  • Replace whole words ie dog with cat and fox with wolf (without applying the rules above)

Output:
Thi quick bruwn wolf jimps over thi luzy friky cat

I started with something like that: (Edited thanks to Ezequiel Muns)

$patterns = array();
$replacements = array();

$patterns[] = "/(?<!\b|[aeiou])[aio](?![aeiou])/";
$replacements[] = "u";

$patterns[] = "/(?<!\b|[aeiou])[eu](?![aeiou])/";
$replacements[] = "i";

$patterns[] = '/ea/';
$replacements[1] = 'i';

$patterns[] = '/dog/';
$replacements[0] = 'cat';

echo preg_replace($patterns, $replacements, $string);

Output:

Thi qiick briwn fix jimps ivir thi lizy friiky dig


Edited:

As you can see the problem is that every rule gets overwritten by the previous rule.

Example 'fox':

  1. rule: turns fox into fux
  2. rule: turns fux into fix

Is there a way to avoid the following rule(s) if the character was already been effected by the previous rule?

Does this makes sense?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

鲸落 2024-09-20 18:59:26

首先,您需要明确替换条件,您的规则规定“不在单词开头且不在元音之前/之后”,但您尚未在正则表达式中实现这一点。您可以使用 Negative Lookahead/Lookbehind 来完成此操作。例如:

  1. 将 a、i、o 替换为 u(如果不在单词开头且不在元音之前/之后)

可实现方式:

$patterns[] = "/(?<!\b|[aeiou])[aio](?![aeiou])/";
$replacements[] = "u";

此方法可用于实现前 3 个规则。

下一个问题是“fox”和“dog”将受到前 3 个规则的影响,因此您应该将更改版本替换为“wolf”和“cat”。所以对于狗=> cat:

$patterns[] = "/\bdug\b/";
$replacements[] = "cat";

注意:由于 preg_replace 处理数组的方式,最好不要在 $patterns 和 $replacements 数组中使用索引,因为这些可能会产生误导。像我上面那样成对使用 [] 运算符,这样您就总是知道什么与什么搭配。

第 2 部分:

啊哈。我懂了。您需要使替换件成为独家的。

您可以使用与第一种情况(即有问题的情况)相匹配的正则表达式。然后,您可以使用 preg_replace 的一个有趣而奇怪的功能:当您添加 e 修饰符时,替换字符串将被评估为 PHP 代码。将此与捕获组结合起来,您可以根据匹配的内容决定是输出 u 还是 i

$patterns[] = "/(?<!\b|[aeiou])([aeiou])(?![aeiou])/e";
$replacements[] = '("$1" == "e" || "$1" == "u")? "i":"u"';

*注意元音匹配类周围的 /e 和 ()。

First you need to be explicit about the replacement conditions, your rules say 'not at the begining of a word and not before/after a vowel' but you have not implemented that in the regex. You can do this using Negative Lookahead/Lookbehind. For example:

  1. Replace a, i, o with u (if not at the beginning of a word & if not before/after a vowel)

Can be implemented with:

$patterns[] = "/(?<!\b|[aeiou])[aio](?![aeiou])/";
$replacements[] = "u";

This method can be used to implement the first 3 rules.

The next problem is that 'fox' and 'dog' will be affected by the first 3 rules, so you should replace the changed version to 'wolf' and 'cat'. So for dog => cat:

$patterns[] = "/\bdug\b/";
$replacements[] = "cat";

Note: Because of the way preg_replace works with arrays, it's much better to not use indexes in the $patterns and $replacements arrays, since these can be misleading. Use the [] operator in pairs like I did above, so you always know what goes with what.

Part 2:

Aha. I see. You need to make the replacement exlusive.

You could use a regex that matches both the first cases, which are the problematic ones. Then you can use an interesting weird feature of preg_replace: When you add the e modifier, the replace string is instead evaluated as PHP code. Combining this with capturing groups, it will allow you to decide whether to output a u or an i according to what you matched.

$patterns[] = "/(?<!\b|[aeiou])([aeiou])(?![aeiou])/e";
$replacements[] = '("$1" == "e" || "$1" == "u")? "i":"u"';

*Note the /e and the () around the vowel matching class.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文