3

我有一个由术语组成的数组,其中一些包含重音字符。我做一个这样的preg grep

$data= array('Napoléon','Café');
$result = preg_grep('~' . $input . '~i', $data);

因此,如果用户输入“le”,我还希望匹配结果“Napoléon”,这不适用于 ablove 命令。

我做了一些搜索,发现这个功能可能是相关的

preg_match("/[\w\pL]/u",$var);

我怎样才能将这些结合起来并使其发挥作用?

4

2 回答 2

3

仅使用正则表达式模式是不可能的。这不是因为你不能告诉正则表达式引擎匹配所有的“e”和类似的东西。但是,可以首先对输入数据(数组和搜索输入)进行规范化,然后搜索规范化数据,但返回非规范化数据的结果。

在下面的示例中,我使用音译来进行这种规范化,我想这就是您要寻找的:

$data = ['Napoléon', 'Café'];

$result = array_translit_search('le', $data);
print_r($result);

$result = array_translit_search('leó', $data);
print_r($result);

示例性输出是:

Array
(
    [0] => Napoléon
)
Array
(
    [0] => Napoléon
)

如上所述,搜索函数本身相当简单,转写输入,执行preg_grep然后返回原始输入匹配:

/**
 * @param string $search
 * @param array $data
 * @return array
 */
function array_translit_search($search, array $data) {

    $transliterator = Transliterator::create('ASCII-Latin', Transliterator::REVERSE);
    $normalize      = function ($string) use ($transliterator) {

        return $transliterator->transliterate($string);
    };

    $dataTrans   = array_map($normalize, $data);
    $searchTrans = $normalize($search);
    $pattern     = sprintf('/%s/i', preg_quote($searchTrans));
    $result      = preg_grep($pattern, $dataTrans);
    return array_intersect_key($data, $result);
}

此代码需要Transliterator来自 Intl 扩展名,您可以将其替换为任何其他类似的音译或翻译功能。

顺便说一句,我不建议在str_replace这里使用。如果您需要回退到翻译表,请strtr改用。这就是你要找的。但我更喜欢一个自带翻译的库,特别是如果它是 Intl 库,你通常无法击败它。

于 2012-12-28T17:11:43.617 回答
1

你可以这样写:

$data = array('Napoléon','Café');
// do something with your input, but for testing purposes it will be simply as you wrote in your example
$input = 'le';

foreach($data as $var) {
  if (preg_match("/".str_replace(array("é"....), array("e"....), $input)."/i", str_replace(array("é"....), array("e"....), $var))) 
    //do something as there is a match
}

实际上在这种情况下你甚至不需要正则表达式,简单strpos就足够了。

于 2012-12-28T16:50:14.677 回答