正则表达式 - 两个被捕获的组,其中一个或两个必须在场

时间:2018-04-19 01:43:55

标签: php regex .htaccess

我有以下链接结构:

/type1
/type2
/type3

这些链接对应于网站的默认语言。不幸的是,客户端并不想在URL前面添加默认语言以保持一致性,因此只有其他语言才会有以下URL:

/en    
/en/type1
/de/type2
/de
/fr/type3
/fr

还有很多其他变量,但只有这部分是动态的。我的正则表达式开始如下:

(en|de|fr)?\/?(type1|type2|type3)?\/?

这基本上意味着捕获语言(如果存在),然后捕获页面(如果存在)。但是它执行的匹配比所需要的多得多,并且还会捕获空字符串等。

我试图找出如何捕获所有这些选项:

/en
/en/type1
/type1

在一个表达式中,当然如果可能的话。如何才能使这两个组中的一组成为必需,所以基本上URL既有两个,也有其中一个,但从来没有?我结合前瞻查看了反向引用,但我认为我在这里错过了一些重要信息...

我希望保留这些群组,以便group1 = languagegroup2 = page

2 个答案:

答案 0 :(得分:0)

我想不出用一个正则表达式做你想要的方法。但是,另一种可能性是使用单个正则表达式来匹配您想要的匹配 URL模式。然后,使用简短的PHP脚本来提取语言(如果存在)和页面:

$path = "/de/type1";
if (preg_match("/^(?:\/(?:en|de|fr))?(?:\/(?:type1|type2|type3))?$/i", $path, $match)) {
    $parts = preg_split("/\//", $path);
    if (sizeof($parts) == 3) {
        echo "language: " . $parts[1] . ", page: " . $parts[2];
    }
    else {
        if (preg_match("/^(?:en|de|fr)$/i", $parts[1], $match)) {
            echo "language: " . $parts[1] . ", page:";
        }
        else {
            echo "language: default, page: " . $parts[1];
        }
    }
}

Demo

这是我用来匹配的模式:

^(?:/(?:en|de|fr))?(?:/(?:type1|type2|type3))?$

它允许/(type1|type2|type3),可选地以语言路径开头。

答案 1 :(得分:0)

这个会给你一个或者另一个(以先到者为准),但不要求如果你提供两者,它们是匹配的(例如你可以指定/ en / type3,它会给你/ en ):

<?php
$pat = '~(/(?:en|de|fr)\b|/type\d\b)~';
$test = ['/en', '/type1', '/en/type1', '/en/type3', '/english/type1'];
foreach ($test as $t) if (preg_match($pat, $t, $match)) echo "'{$t}' = '{$match[1]}'\n";
?>

这给了你:

'/en' = '/en'
'/type1' = '/type1'
'/en/type1' = '/en'
'/en/type3' = '/en'
'/english/type1' = '/type1'

(最后一个例子是为了说明为什么你需要模式中的\ b)