【问题标题】:PHP Regex to find pattern and wrap in anchor tagsPHP 正则表达式查找模式并包装在锚标记中
【发布时间】:2017-02-26 12:29:36
【问题描述】:

我有一个包含电影名称和发行年份的字符串。我希望能够检测到标题(年份)模式,如果匹配,则将其包装在锚标签中。

包装很容易。但是,如果我不知道电影的名称是什么,是否可以编写一个正则表达式来匹配这个模式?

例子:

$str = 'A random string with movie titles in it. 
Movies like The Thing (1984) and other titles like Captain America Civil War (2016). 
The movies could be anywhere in this string. 
And some movies like 28 Days Later (2002) could start with a number.';

因此模式将始终为Title(以大写字母开头)并以(Year) 结尾。

这是我目前得到的:

if(preg_match('/^\p{Lu}[\w%+\/-]+\([0-9]+\)/', $str)){
    error_log('MATCH');
}
else{
    error_log('NO MATCH');
}

这目前不起作用。据我了解,这是它应该做的:

^\p{Lu} //match a word beginning with an uppercase letter

[\w%+\/-] //with any number of characters following it

+\([0-9]+\) //ending with an integer

我哪里错了?

【问题讨论】:

  • ([A-Z]{1}[a-z]+\s?)+\(\d+\) 这就是您要找的。为了便于测试正则表达式模式,我使用 RegExr (regexr.com)
  • 一行可以立即以电影标题开始吗?如果一部电影是像1984 (1984) 这样的全数字电影怎么办?这是需要照顾的东西吗? siam 的解决方案虽然非常聪明,但与 1984 (1984) is a movie over 30 years old. 不匹配我只是想确保您提供的示例涵盖所有可能的情况。
  • 另一方面,toto 的正则表达式捕获 1984 (1984) is a movie over 30 years old. 并节省了 164 步。它似乎优于我的扩展样本。

标签: php regex pattern-matching preg-replace preg-match


【解决方案1】:

下面的 regex 应该这样做:

(?-i)(?<=[a-z]\s)[A-Z\d].*?\(\d+\)

说明

  • (?-i)区分大小写
  • (?&lt;=[a-z]\s) 查找任何小写字母和空格
  • [A-Z\d] 匹配大写字母或数字
  • .*? 匹配任意字符
  • \(\d+\) 匹配任何数字,包括括号

DEMO

PHP

<?php
$regex = '/(?-i)(?<=[a-z]\s)[A-Z\d].*?\(\d+\)/';
$str = 'A random string with movie titles in it.
       Movies like The Thing (1984) and other titles like Captain America Civil War (2016).
       The movies could be anywhere in this string.
       And some movies like 28 Days Later (2002) could start with a number.';
preg_match_all($regex, $str, $matches);
print_r($matches);
?>

【讨论】:

  • 很好的答案,感谢您的解释。我的路还很长!
【解决方案2】:

这个正则表达式完成了这项工作:

~(?:[A-Z][a-zA-Z]+\s+|\d+\s+)+\(\d+\)~

说明:

~               : regex delimiter
  (?:           : start non capture group
    [A-Z]       : 1 capital letter, (use \p{Lu} if you want to match title in any language)
    [a-zA-Z]+   : 1 or more letter,  if you want to match title in any language(use \p{L})
    \s+         : 1 or more spaces
   |            : OR
    \d+         : 1 or more digits
    \s+         : 1 or more spaces
  )+            : end group, repeated 1 or more times
  \(\d+\)       : 1 or more digits surrounded by parenthesis, (use \d{4} if the year is always 4 digits)
~               : regex delimiter

实施:

$str = 'A random string with movie titles in it. 
Movies like The Thing (1984) and other titles like Captain America Civil War (2016). 
The movies could be anywhere in this string. 
And some movies like 28 Days Later (2002) could start with a number.';

if (preg_match_all('~(?:[A-Z][a-zA-Z]+\s+|\d+\s+)+\(\d+\)~', $str, $match)) {
    print_r($match);
    error_log('MATCH');
}
else{
    error_log('NO MATCH');
}

结果:

Array
(
    [0] => Array
        (
            [0] => The Thing (1984)
            [1] => Captain America Civil War (2016)
            [2] => 28 Days Later (2002)
        )

)
MATCH

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-16
    • 1970-01-01
    相关资源
    最近更新 更多