【问题标题】:PHP preg_replace for All Types of Year Formats (YYYY, YYYY-YYYY, YYYY - YYYY)PHP preg_replace 适用于所有类型的年份格式(YYYY、YYYY-YYYY、YYYY - YYYY)
【发布时间】:2018-05-18 02:48:31
【问题描述】:

尝试仅使用 preg_replace 对包含诸如 2018 1950-2018 和 1950 - 2018 等年份格式的字符串进行修改(添加 html 换行符)

$j = preg_replace('/([0-9]{4}) - ([0-9]{4})/', '<br>* ${1} - ${2}</strong>', $j);
$j = preg_replace('/([0-9]{4})-([0-9]{4})/', '<br>* ${1} - ${2}', $j);
$j = preg_replace('/\s+(19[5-9][0-9]|20(0[0-9]|10))\s+/', '<br>* ${1} </strong>', $j);

我的偏好是正则表达式是年 1950 - 2020

前两个工作正常(尽管我无法正确获取范围),但最后一个正在捕获所有实例

喜欢:

* 2007
** 2008 - 2013

等

尝试使用^ 和$ 来表示开始和结束。但第三个总是与前两个匹配。

我怎样才能完全分离这些年份格式,以便我可以单独更改每个格式?

示例代码:

<?php

$string = 'Detailed Applications: 2005-2006 Volkswagen | 2006 Volkswagen Golf 2.0L 1984CC 121Cu. In. l4 GAS SOHC Naturally Aspirated | 2005 Volkswagen Beetle 2.0L 1984CC 121Cu. In. l4 GAS DOHC Naturally Aspirated | 2005 - 2006 Volkswagen Golf';

echo $string;

echo '<br><br>';

$string = preg_replace('/([0-9]{4}) - ([0-9]{4})/', '<br /><strong>(YYYY - YYYY)* ${1} - ${2}</strong>', $string);
$string = preg_replace('/([0-9]{4})-([0-9]{4})/', '<br /><strong>(YYYY-YYYY)* ${1} - ${2}</strong>', $string);
$string = preg_replace('/(\d19[5-9][0-9]|20[0-9][0-9])(?!\s?-)/', '<br /><strong>(YYYY)* ${1} </strong>', $string);

echo $string;

输出

Detailed Applications: 
(YYYY-YYYY)* 2005 - 
(YYYY)* 2006 Volkswagen | 
(YYYY)* 2006 Volkswagen Golf 2.0L 1984CC 121Cu. In. l4 GAS SOHC Naturally Aspirated | 
(YYYY)* 2005 Volkswagen Beetle 2.0L 1984CC 121Cu. In. l4 GAS DOHC Naturally Aspirated | 
(YYYY - YYYY)* 2005 - 
(YYYY)* 2006

对不起,真的很困惑。

基本上我正在做的是尝试循环它并只是做一个换行符(不爆炸字符串)......显然使用我的正则表达式它在它自己的行上输出每个......

试图得到这样的输出

Detailed Applications: 
(YYYY-YYYY)* 2005 - 2006 Volkswagen | 
(YYYY)* 2006 Volkswagen Golf 2.0L 1984CC 121Cu. In. l4 GAS SOHC Naturally Aspirated | 
(YYYY)* 2005 Volkswagen Beetle 2.0L 1984CC 121Cu. In. l4 GAS DOHC Naturally Aspirated | 
(YYYY - YYYY)* 2005 - 2006

但是是的..这是我得到的最好的

$j = preg_replace('/([0-9]{4}) - ([0-9]{4})/', '<br /><strong>* ${1} - ${2}</strong>', $j);
$j = preg_replace('/([0-9]{4})-([0-9]{4})/', '<br /><strong>* ${1} - ${2}</strong>', $j);
$j = preg_replace('/(19[5-9][0-9]|20(0[0-9]|20))(?!\s?-)/', '<br /><strong>* ${1} </strong>', $j);

所以这是我的脚本的实际摘录

2007 Chevy Silverado Pickup new body style models 2008-2013 Chevy Silverado All Models 2014 Chevy Silverado 2500HD 3500HD 2007 GMC Sierra Pickup new body style models 2008-2013 GMC Sierra All Models 2014 GMC Sierra 2500HD 3500HD 2007-2013 Chevy Tahoe 2007-2013 Chevy Suburban 2007-2013 Chevy Avalanche 2007-2013 GMC Yukon Yukon XL Yukon Denali

直接向上一行(发布上面的示例脚本,因为该行不包含YYYY - YYYY 变体...)

输出是这样的

* 2007 Chevy Silverado Pickup new body style models 
* 2008 - 2013 Chevy Silverado All Models 2014 Chevy Silverado 2500HD 3500HD 
* 2007 GMC Sierra Pickup new body style models 
* 2008 - 2013 GMC Sierra All Models 2014 GMC Sierra 2500HD 3500HD 
* 2007 - 2013 Chevy Tahoe 
* 2007 - 2013 Chevy Suburban 
* 2007 - 2013 Chevy Avalanche 
* 2007 - 2013 GMC Yukon Yukon XL Yukon Denali

除了* 2008 - 2013 Chevy Silverado All Models 2014 Chevy Silverado 2500HD 3500HD 2014 没有进入新行之外,一切都很好......而且我也无法弄清楚如何做年份范围(doh!)即使引用这个javascript regex validate years in range

【问题讨论】:

  • 好的。有什么问题吗?
  • 我怎样才能完全分离这些年份格式,以便我可以单独更改每个格式?
  • 那么您能否发布一个涵盖所有案例的示例输入字符串,并为该示例字符串发布您想要的输出?
  • 第三种模式需要严格验证吗?你不希望** 重复出现对吧?
  • Tim 的回答有所帮助,但我在实现后向检查方面遇到了麻烦……负前瞻工作有效,但仍与 2008- * 2013 之类的输入匹配

标签: php regex date preg-replace pcre


【解决方案1】:

简化替换逻辑的一种方法是识别出您希望在每 4 位数年份之后添加一个 &lt;br&gt;,该年份 不是,后跟一个破折号,或者一个空格和一个破折号。我们可以很容易地使用否定前瞻来表达这一点:

(\d{4})(?!\s?-)

代码示例:

$input = "that contains year formats like 2018 1950-2018 and 1950 - 2018";
echo preg_replace("/(\d{4})(?!\s?-)/", "$1<br>", $input);

that contains year formats like 2018<br> 1950-2018<br> and 1950 - 2018<br>

Demo

【讨论】:

    【解决方案2】:

    preg_replace_callback() 将让您验证/提取目标子字符串并一次性进行条件替换。

    • &lt;br&gt; 必须写在所有年份/年份范围之前,只要它不是字符串的开头即可。第一个捕获组是\s*,因此它将在您的目标年份/年份范围之前捕获零个或多个空白字符。此元素将始终以 [1] 的形式存在于 $m 数组中。
    • 第二个捕获组是第一个或唯一的年份值。这是实现回调函数所必需的。这是$m 数组中的[2]。
    • 对于可选的第二年值,它必须跟在零个或多个空格后面,然后是一个连字符,然后是零个或多个空格。因为没有跟在这个捕获组后面的捕获组,所以 php 只会在找到时为这个组生成一个元素——isset() 用于检查[3] 是否存在。
    • 最初,我使用\b 来确保年份值不是较大数字子字符串的子字符串,但您的字符串格式允许使用空格匹配来确认准确匹配。

    代码:(Demo) (Pattern Demo)

    $string = "2007 Chevy Silverado Pickup new body style models 2008-2013 Chevy Silverado All Models 2014 Chevy Silverado 2500HD 3500HD 2007 GMC Sierra Pickup new body style models 2008 - 2013 GMC Sierra All Models 2014 GMC Sierra 2500HD 3500HD 2007-2013 Chevy Tahoe 2007-2013 Chevy Suburban 2007   -   2013 Chevy Avalanche 2007-2013 GMC Yukon Yukon XL Yukon Denali";
    
    echo preg_replace_callback('~(\s*)(19[5-9]\d|20[0-4]\d)(?:\s*-\s*(19[5-9]\d|20[0-4]\d))?(?=\s)~', function($m) {
        //var_export($m);  // un-comment if you want to see each $m array
        //echo "\n---\n";
            return (strlen($m[1]) ? "\n" : "")
                    . "<strong>*{$m[2]}"
                    . (isset($m[3]) ? " - {$m[3]}" : "")
                    . "</strong>";
        },
        $string);
    

    输出:

    <strong>*2007</strong> Chevy Silverado Pickup new body style models
    <strong>*2008 - 2013</strong> Chevy Silverado All Models
    <strong>*2014</strong> Chevy Silverado 2500HD 3500HD
    <strong>*2007</strong> GMC Sierra Pickup new body style models
    <strong>*2008 - 2013</strong> GMC Sierra All Models
    <strong>*2014</strong> GMC Sierra 2500HD 3500HD
    <strong>*2007 - 2013</strong> Chevy Tahoe
    <strong>*2007 - 2013</strong> Chevy Suburban
    <strong>*2007 - 2013</strong> Chevy Avalanche
    <strong>*2007 - 2013</strong> GMC Yukon Yukon XL Yukon Denali
    

    【讨论】:

    • @Brian ...好的,我现在已经完成了我的解决方案。 (第一个sn-p不是专业级的)
    • 绝对完美的响应和输出,感激不尽。 RegEX 和回调函数是我知道我需要了解的两件事——你可以用它们做很多非常酷的事情。再次感谢您花一天时间研究您的代码并将其调整到我的范围。
    • badabing ~(\s+)?\b(19[5-9]\d|20[0-4]\d)(?:\s*-\s*(\d19[5-9]\d|20[0-4]\d))?\b~' - 对于我试图达到的范围(我认为 :) 仍然需要做一些测试)。 RegEX 测试器也有很大的帮助.. 开始变得更有意义了。
    • 很高兴回答您的后续问题。
    • @Brian 我对我的解决方案/答案并不完全满意,因此我进行了一些改进,合并了您更严格的年份子模式,并更好地解释了我的流程。让我知道我是否应该为您解决任何问题。
    猜你喜欢
    • 1970-01-01
    • 2021-06-14
    • 1970-01-01
    • 2013-03-21
    • 2016-01-02
    • 1970-01-01
    • 1970-01-01
    • 2013-08-31
    • 2021-12-18
    相关资源
    最近更新 更多