为什么模式匹配一​​个单词,而有两个相同的单词?

时间:2017-04-28 10:47:18

标签: php regex

请看一下:

enter image description here

如您所见 regex101 中只有一个,但浏览器会匹配两个相同的单词。那么为什么 regex101 无法匹配第二个单词呢?无论如何,我需要匹配两个单词(或更多,如果存在)

注意到它与g标志无关。因为我已经在小提琴中使用过它。

以下是fiddle

2 个答案:

答案 0 :(得分:3)

处理此类文本很难以后再使用。根据@ Wiktor的解决方案,您必须找到每个字母的不同表示形式,以便将搜索词从مجلس更改为احمدی نژاد之类的其他内容。

这就是为什么normalization进程很方便的原因:

  

规范化是一个涉及转换字符和转换的过程   字符序列成为正式定义的底层   表示。当需要文本时,这个过程是最重要的   比较排序和搜索, 但它也在存储时使用   文本以确保文本以一致的表示形式存储。

我们需要使用Normalizer::normalize()在第一个位置对输入字符串进行规范化,然后在正则表达式中不做任何更改,我们可以安全地在其上运行preg_match_all

<?php

$text = <<< 'STR'
یک نماینده مجلس عنوان کرد: ﺩﺭ ﺩﻭﺭﻩ ﺍﺣﻤﺪﯼﻧﮋﺍﺩ ﻣﺮﺩﻡ ﺩﺭ
ﺭﻓﺎﻩ ﺑﻮﺩﻧﺪ !/دولت سابق تنها دولتی که پس از انقلاب به مردم خدمت کرد! ﻳﻚ
ﻧﻤﺎﯾﻨﺪﻩ ﮔﺮﻭﻩ ﭘﺎﻳﺪﺍﺭی دﺭ ﻣﺠﻠﺲ ﺷﻮﺭﺍﯼ ﺍﺳﻼﻣﯽ ﺩﺭ ﭘﺎﺳﺦ ﺑﻪ ﺳﺆﺍﻟﯽ ﺩﺭ ﻣﻮﺭﺩ
ﺑﺎﺯﮔﺸﺖ ﺍﺣﻤﺪﯼﻧﮋﺍﺩ ﺑﻪ ﻋﺮﺻﻪ ﺍﻧﺘﺨﺎﺑﺎﺕ ﺍﻇﻬﺎﺭ ﺩﺍﺷﺖ : ﻣﺎ ﺍﻣﯿﺪﻭﺍﺭﯾﻢ ﺍﯾﻦ ﺍﺗﻔﺎﻕ
ﺑﯿﻔﺘﺪ ﻭ ﺍﺣﻤﺪﯼﻧﮋﺍﺩ ﺑﺮﺍﯼ ﺷﺮﮐﺖ ﺩﺭ ﺍﻧﺘﺨﺎﺑﺎﺕ ﺣﺎﺿﺮ ﺷﻮﺩ چرا که دولت وی تنها
دولتی است که پس از انقلاب به مردم خدمت کرده است.
STR;


$normalizedText = normalizer_normalize( $text , Normalizer::NFKC );
preg_match_all('~مجلس~', $normalizedText, $matches);

print_r($matches);

输出:

Array
(
    [0] => Array
        (
            [0] => مجلس
            [1] => مجلس
        )

)

注意:需要启用php_intl.dll扩展名。

Live demo

答案 1 :(得分:1)

使用不同的字符编写单词,这些字符看起来相同但具有不同的Unicode代码。

  • 第一个字:\uFEE3\uFEA0\uFEE0\uFEB2
  • 未匹配的名称(名称中为... FORM):\u0645\u062C\u0644\u0633

以下是代码:

‎FEE3  ARABIC LETTER MEEM INITIAL FORM
‎0645  ARABIC LETTER MEEM

‎FEA0  ARABIC LETTER JEEM MEDIAL FORM
‎062C  ARABIC LETTER JEEM

‎FEE0  ARABIC LETTER LAM MEDIAL FORM
‎0644  ARABIC LETTER LAM

‎FEB2  ARABIC LETTER SEEN FINAL FORM
‎0633  ARABIC LETTER SEEN

您无法将两者都与单词的文字表示相匹配,您需要使用两个/所有变体的替换,或者为这些字符使用字符类:

[\x{FEE3}\x{0645}][\x{FEA0}\x{062C}][\x{FEE0}\x{0644}][\x{FEB2}\x{0633}]

请参阅regex demo

A PHP demo

$re = '/[\x{FEE3}\x{0645}][\x{FEA0}\x{062C}][\x{FEE0}\x{0644}][\x{FEB2}\x{0633}]/u';
$str = 'یک نماینده مجلس عنوان کرد: ﺩﺭ ﺩﻭﺭﻩ ﺍﺣﻤﺪﯼﻧﮋﺍﺩ ﻣﺮﺩﻡ ﺩﺭ ﺭﻓﺎﻩ ﺑﻮﺩﻧﺪ !/دولت سابق تنها دولتی که پس از انقلاب به مردم خدمت کرد! ﻳﻚ ﻧﻤﺎﯾﻨﺪﻩ ﮔﺮﻭﻩ ﭘﺎﻳﺪﺍﺭی دﺭ ﻣﺠﻠﺲ ﺷﻮﺭﺍﯼ ﺍﺳﻼﻣﯽ ﺩﺭ ﭘﺎﺳﺦ ﺑﻪ ﺳﺆﺍﻟﯽ ﺩﺭ ﻣﻮﺭﺩ ﺑﺎﺯﮔﺸﺖ ﺍﺣﻤﺪﯼﻧﮋﺍﺩ ﺑﻪ ﻋﺮﺻﻪ ﺍﻧﺘﺨﺎﺑﺎﺕ ﺍﻇﻬﺎﺭ ﺩﺍﺷﺖ : ﻣﺎ ﺍﻣﯿﺪﻭﺍﺭﯾﻢ ﺍﯾﻦ ﺍﺗﻔﺎﻕ ﺑﯿﻔﺘﺪ ﻭ ﺍﺣﻤﺪﯼﻧﮋﺍﺩ ﺑﺮﺍﯼ ﺷﺮﮐﺖ ﺩﺭ ﺍﻧﺘﺨﺎﺑﺎﺕ ﺣﺎﺿﺮ ﺷﻮﺩ چرا که دولت وی تنها دولتی است که پس از انقلاب به مردم خدمت کرده است.';
preg_match_all($re, $str, $matches);
print_r($matches[0]);

输出:

Array
(
    [0] => مجلس
    [1] => ﻣﺠﻠﺲ
)