反向正则表达式,从正则表达式创建字符串 [英] Reverse regular expression, create string from regex

查看:117
本文介绍了反向正则表达式,从正则表达式创建字符串的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个多语言网站,并选择使用每种语言的自定义网址,例如:

/en/cities/paris//nl/斯泰登/巴黎/

两者都指向 Cities 控制器的 Index 方法.

在每个页面上都有一个切换语言的选项,它会在我的路由中查找以匹配控制器、视图和语言.

因此,如果我在荷兰语页面上,它会找到英文版的正确网址,即城市"而不是斯登".

一切都很好,直到我开始使用更复杂的正则表达式.

我有这些正则表达式可以匹配我想要的 URL:

#^en/cities/([^/]+?)/$##^nl/steden/([^/]+?)/$#

在我的代码中,我可以访问正在匹配的变量,在本例中为 'paris'.是否可以反转"这个正则表达式并让它打印en/cities/paris/"

如果没有......我将如何链接到同一页面的不同版本,考虑到 URL 不同......最好让它尽可能可编程.

在一个有点类似的问题中,有人回答 (http://stackoverflow.com/a/7070734/616398) 正则表达式的本质是匹配无限数量的结果......所以它可能是不可能的.

将字符串/URL 转换为一组匹配的标准以在 MVC 中使用是很容易的,但反过来说……不幸的是,情况并非如此.

解决方案

是的,这是可能的!对于这种情况,我编写了以下解决方案:

$regex = '#^en/cities/([^/]+?)/$#';$replace = array('巴黎');$result = preg_replace_callback('#^\^|\([^)]*\)|\$$#', function($m)use($replace){静态 $index = 0;if($m[0] === '^' || $m[0] === '$'){return '';}if(isset($replace[$index])){返回 $replace[$index++];}返回 $m[0];}, substr($regex, 1, -1));回声 $result;//en/城市/巴黎/

在线演示

我让它变得灵活",所以你可以添加更多的价值!

$regex = '#^en/cities/([^/]+?)/region/([^/]+?)$#';//<<<改变了$replace = array('巴黎', 'nord');//<<<改变了$result = preg_replace_callback('#^\^|\([^)]*\)|\$$#', function($m)use($replace){静态 $index = 0;if($m[0] === '^' || $m[0] === '$'){return '';}if(isset($replace[$index])){返回 $replace[$index++];}返回 $m[0];}, substr($regex, 1, -1));回声 $result;//en/cities/paris/region/nord

在线演示

<小时>

说明:

$regex = '#^en/cities/([^/]+?)/region/([^/]+?)$#';//正则表达式反转"$replace = array('巴黎', 'nord');//要注入"的值/* 正则表达式解释:# 开始分隔符^\^ 在开头匹配^"(我们想摆脱这个)|或者\([^)]*\) 匹配(",任何零次或多次,直到找到)",)"|或者\$$ 匹配末尾的$"(我们想解决这个问题)# 结束分隔符*/$result = preg_replace_callback('#^\^|\([^)]*\)|\$$#', function($m)use($replace){静态 $index = 0;//设置索引0,注意这个变量只能在这个(匿名)函数中访问if($m[0] === '^' || $m[0] === '$'){return '';}//在开始和结束时使用 ^/$if(isset($replace[$index])){//总是检查它是否存在,例如如果 $replace 中没有足够的值,这将防止错误...返回 $replace[$index++];//返回注入的值,同时将 $index 增加 1}返回 $m[0];//如果没有足够的值,这将返回 ([^/]+?) 在这种情况下,您可能希望将其删除以不将其包含在输出中}, substr($regex, 1, -1));//substr($regex, 1, -1) =>使用分隔符回声 $result;//输出 o_o

<块引用>

注意:这仅适用于 PHP 5.3+

I am working on a multilingual site and have chosen to use custom URLs per language as well, so for example:

/en/cities/paris/
/nl/steden/paris/

Both point to the Index method of the Cities controller.

On every page there's an option to switch language and it will look in my routes to match controller, view and language.

So if I'm on the Dutch page, it will find the proper url for the English version, which will be 'cities' instead of 'steden'.

All worked fine, up until I started using more complex regular expressions.

I have these regular expressions that will match my desired URLs:

#^en/cities/([^/]+?)/$#
#^nl/steden/([^/]+?)/$#

In my code I have access to the variable that's being matched, 'paris' in this example. Would it be possible to 'reverse' this regular expression and have it print 'en/cities/paris/'

If not.. how would I go about having links to different versions of the same page, considering the URLs are different.. preferably have it as programmable as possible.

In a somewhat similar question, someone answered (http://stackoverflow.com/a/7070734/616398) that the essense of regex is to match an infinite number of results.. so it might not be possible.

It's quite easy to go from a string/URL to a set of matched criteria to use in a MVC, but the other way around.. not so much, unfortunately.

解决方案

Yes that's possible ! For this case I've coded the following solution:

$regex = '#^en/cities/([^/]+?)/$#';
$replace = array('paris');

$result = preg_replace_callback('#^\^|\([^)]*\)|\$$#', function($m)use($replace){
    static $index = 0;
    if($m[0] === '^' || $m[0] === '$'){return '';}
    if(isset($replace[$index])){
        return $replace[$index++];
    }
    return $m[0];
}, substr($regex, 1, -1));
echo $result; // en/cities/paris/

Online demo

I've made it "flexible" so you can add more values to it !

$regex = '#^en/cities/([^/]+?)/region/([^/]+?)$#'; // <<< changed
$replace = array('paris', 'nord'); // <<< changed

$result = preg_replace_callback('#^\^|\([^)]*\)|\$$#', function($m)use($replace){
    static $index = 0;
    if($m[0] === '^' || $m[0] === '$'){return '';}
    if(isset($replace[$index])){
        return $replace[$index++];
    }
    return $m[0];
}, substr($regex, 1, -1));
echo $result; // en/cities/paris/region/nord

Online demo


Explanation:

$regex = '#^en/cities/([^/]+?)/region/([^/]+?)$#'; // Regex to "reverse"
$replace = array('paris', 'nord'); // Values to "inject"

/*  Regex explanation:
   #   Start delimiter
       ^\^         Match "^" at the begin (we want to get ride of this)
       |           Or
       \([^)]*\)   Match "(", anything zero or more times until ")" is found, ")"
       |           Or
       \$$         Match "$" at the end (we want to get ride of this)
   #   End delimiter
*/

$result = preg_replace_callback('#^\^|\([^)]*\)|\$$#', function($m)use($replace){
    static $index = 0; // Set index 0, note that this variable is only accessible in this (anonymous) function
    if($m[0] === '^' || $m[0] === '$'){return '';} // Get ride of ^/$ at the begin and the end
    if(isset($replace[$index])){ // Always check if it exists, for example if there were not enough values in $replace, this will prevent an error ...
        return $replace[$index++]; // Return the injected value, at the same time increment $index by 1
    }
    return $m[0]; // In case there isn't enough values, this will return ([^/]+?) in this case, you may want to remove it to not include it in the output
}, substr($regex, 1, -1)); // substr($regex, 1, -1) => Get ride of the delimiters
echo $result; // output o_o

Note: This works only on PHP 5.3+

这篇关于反向正则表达式,从正则表达式创建字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆