【问题标题】:PHP Regex on CD TracklistsCD 曲目列表上的 PHP 正则表达式
【发布时间】:2013-11-19 20:39:01
【问题描述】:

我正在使用preg_match 来格式化曲目列表,以便将曲目编号、标题和持续时间分隔到表格中各自的单元格中:

<td>01</td><td>Track Title</td><td>01:23</td>

问题在于曲目本身可以采用以下任何形式(曲目编号和持续时间上的前导零并不总是存在):

01. Track Title (01:23)
01. Track Title 01:23
01. Track Title
1 Track Title (01:23)
1 Track Title 01:23
1 Track Title

以下仅适用于带有时间戳的曲目:

/([0-9]+)\.?[\s+](.*)[\s+](\?[0-5]?[0-9]:[0-5][0-9]\)?)/

所以我在时间戳中添加了?

/([0-9]+)\.?[\s+](.*)[\s+]((\?[0-5]?[0-9]:[0-5][0-9]\)?)?/

这适用于没有时间戳的曲目,但有时间戳的曲目最终会在标题上加上时间戳,如下所示:

<td>01</td><td>Track Title 01:23</td><td></td>

编辑:曲目列表是纯文本的,在解析之前从 SQL 表中提取。

【问题讨论】:

  • +1 为您的尝试。使用 html 解析器不会更容易吗?想想phpQuery
  • 您总是可以做一些逻辑并使用多个正则表达式 - 例如检查字符串末尾附近的“:”是否存在,然后使用一个正则表达式以任何格式获取时间戳。这种方法的优点是,当你发现另一个极端情况(比如一首名为 0:00 的歌曲或其他东西)时,修复比尝试修复一个巨大的正则表达式更容易。
  • @Karl 与您最后一次编辑,你的意思是没有&lt;td&gt; 标签?
  • @HamZa 抱歉,我忘了补充说曲目列表是纯文本的。所以是的,没有 html 标签。
  • @Karl lolwut,那你为什么要添加它。我来到了这个(\d+)\.?\s*(.*?)\s*(\(\d+:\d+\)|\d+:\d+|$) 解决方案。如果需要,您需要遍历第 3 组并修剪 () ...

标签: php regex preg-match


【解决方案1】:

试试这个:

/^([0-9]+)\.?[\s]+(.*)([\s]+(\(?[0-5]?[0-9]:[0-5][0-9]\)?))?$/U

注意我使用了不贪婪的模式修饰符U 来尝试匹配最小的匹配字符串,并且我已经锚定了字符串的开头和结尾。

【讨论】:

  • 同样的结果,我的朋友 :(
  • @Karl Regexoverflow : (?m)^([0-9]+)\.?\s+(.*?)\s*\(?([0-5]?[0-9]:[0-5][0-9])?\)?$
【解决方案2】:

默认情况下,正则表达式是贪婪的,所以匹配标题.* 的部分会吃掉字符串的其余部分,因为最后一个带有持续时间的部分是可选的。

使用/U 修饰符开启不贪婪的行为 - 寻找PCRE_UNGREEDY on http://us1.php.net/manual/en/reference.pcre.pattern.modifiers.php

【讨论】:

    【解决方案3】:

    怎么样:

    ^([0-9]+)\.?\s+(.*?)(?:\(?([0-5]?[0-9]:[0-5][0-9])\)?)?$
    

    解释:

    正则表达式:

    (?-imsx:^([0-9]+)\.?\s+(.*?)(?:\(?([0-5]?[0-9]:[0-5][0-9])\)?)?$)
    
    matches as follows:
    
    NODE                     EXPLANATION
    ----------------------------------------------------------------------
    (?-imsx:                 group, but do not capture (case-sensitive)
                             (with ^ and $ matching normally) (with . not
                             matching \n) (matching whitespace and #
                             normally):
    ----------------------------------------------------------------------
      ^                        the beginning of the string
    ----------------------------------------------------------------------
      (                        group and capture to \1:
    ----------------------------------------------------------------------
        [0-9]+                   any character of: '0' to '9' (1 or more
                                 times (matching the most amount
                                 possible))
    ----------------------------------------------------------------------
      )                        end of \1
    ----------------------------------------------------------------------
      \.?                      '.' (optional (matching the most amount
                               possible))
    ----------------------------------------------------------------------
      \s+                      whitespace (\n, \r, \t, \f, and " ") (1 or
                               more times (matching the most amount
                               possible))
    ----------------------------------------------------------------------
      (                        group and capture to \2:
    ----------------------------------------------------------------------
        .*?                      any character except \n (0 or more times
                                 (matching the least amount possible))
    ----------------------------------------------------------------------
      )                        end of \2
    ----------------------------------------------------------------------
      (?:                      group, but do not capture (optional
                               (matching the most amount possible)):
    ----------------------------------------------------------------------
        \(?                      '(' (optional (matching the most amount
                                 possible))
    ----------------------------------------------------------------------
        (                        group and capture to \3:
    ----------------------------------------------------------------------
          [0-5]?                   any character of: '0' to '5' (optional
                                   (matching the most amount possible))
    ----------------------------------------------------------------------
          [0-9]                    any character of: '0' to '9'
    ----------------------------------------------------------------------
          :                        ':'
    ----------------------------------------------------------------------
          [0-5]                    any character of: '0' to '5'
    ----------------------------------------------------------------------
          [0-9]                    any character of: '0' to '9'
    ----------------------------------------------------------------------
        )                        end of \3
    ----------------------------------------------------------------------
        \)?                      ')' (optional (matching the most amount
                                 possible))
    ----------------------------------------------------------------------
      )?                       end of grouping
    ----------------------------------------------------------------------
      $                        before an optional \n, and the end of the
                               string
    ----------------------------------------------------------------------
    )                        end of grouping
    ----------------------------------------------------------------------
    

    【讨论】:

      猜你喜欢
      • 2010-09-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-23
      • 2013-05-30
      • 2012-08-03
      • 1970-01-01
      相关资源
      最近更新 更多