【问题标题】:Regular Expressions - two captured groups, either one or both have to be present正则表达式 - 两个捕获的组,一个或两个必须存在
【发布时间】:2018-04-19 01:43:55
【问题描述】:

我有以下链接结构:

/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

【问题讨论】:

    标签: php regex .htaccess


    【解决方案1】:

    我想不出用一个正则表达式来做你想做的事。但是,另一种可能性是使用单个正则表达式来仅 match 您想要的 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),可选地以语言路径开头。

    【讨论】:

    • 感谢您的建议,我会玩一下。奇怪的是,在旧的 Apache 中,我认为它可以像在我的正则表达式之前使用前导斜杠一样有条件地捕获所有内容,
    【解决方案2】:

    这个会给你一个或另一个(以先到者为准),但不要求如果你提供两者,它们匹配(例如,你可以指定/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)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-09-23
      • 2020-09-22
      • 2017-08-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-10
      • 1970-01-01
      相关资源
      最近更新 更多