使用 PhP(歌曲名称)获取特定的正则表达式

Get a specific regex using PhP (Song names)

我一直在努力使用这个特定的正则表达式。

快速背景:

我下载了很多歌曲,给了它们正确的名字等等,但现在我希望它们在数据库中供我练习 AJAX、JSON、SQL 和 PhP.

每首歌都有相同的构建。

ARTIST - SONGNAME ft. ARTIST (ARTIST Remix)

所有斜体都是可选的。到目前为止,我设法获得了以下正则表达式来获取一些数据,但这还不够。

/(.*) - (.*) [ft\.]* (.*)/

然而,这需要 'ft.' 才能工作,并且该部分是可选的。 然后我决定做多个正则表达式,但我从来没有忘记艺术家姓名和歌曲名称,这仍然让我留下了 ft 和 () 部分。

我一直在使用 http://www.phpliveregex.com/ 实时练习一些歌曲。

以下是我要过滤的歌曲名称的一些示例:

Armin van Buuren - Rain ft. Cathy Burton (Urbanstep Remix).mp3
Alpha Drop - Spring Fever.mp3
Beatcore - Tonight ft. Lynn Boyer.mp3
iru1919 - 天狐.mp3

您可以通过在组后添加问号来使组可选:

(ft\.)?

在某些情况下,您可以使用花括号:

{ft\.}?

? 被称为 quantifier

你必须使用像这样的正则表达式:

/(.*) - (.*)( (ft\.)? (.*))?(\([^)]+\))?/

您的正则表达式失败,因为 [ft\.]* 表示 'any of f,t or .',还因为 (.*) - (.*) 之后的 space 与第二个和第四个示例不匹配。

eval.in demo

编辑:

最后,我认为这个正则表达式比我在上面发布的第一个要好:

/(.+) - ((?:(?!(ft\.|\()).)+)( *ft\.[^\(]+)?( *\(([^)]+)\))?\.([^.]+)$/

eval.in demo

它分别匹配艺术家、标题、最终的 ft. 艺术家、最终的混音和文件扩展名。

请注意如果主打歌或主唱中有括号(有可能),则匹配失败。

我不是 regex 专家,所以我的解决方案很粗鲁,但我确信没有更好的解决方案。

定义:

下一个输入: 待进一步检查歌曲信息的字符串。

首先,我会将艺术家与歌曲名称的其余部分分开:

/(.*) - (.*)\.mp3$/

第一个反向引用是 'ARTIST'。第二个是下一个输入。

接下来我会搜索 'ARTIST Remix'(因为这是最容易搜索下一个):

/([^(]*)( \(([^)]*)\))?$/

第一个反向引用是下一个输入。第三个反向引用 ([^)]*) 引用 'ARTIST Remix'。第二个反向引用可以忽略,因为它不需要。它是 space 后跟方括号中的 'ARTIST Remix'。

现在您可以搜索精选 'ARTIST':

/(.*) ft\. (.*)/

如果有特色 'ARTIST',第一个反向引用是 'SONGNAME',第二个是特色 'ARTIST'。但是,如果没有特色 'ARTIST',那么您将得到一个空数组,因为没有匹配项。

当没有特征 'ARTIST',或者更具体地说,没有出现 ft. 时,下一个输入,即要检查的剩余字符串,是 'SONGNAME'。

正如其他人所说,[ft\.]* 将匹配任何列出的字符,以任何顺序,任意次数。

我建议这个正则表达式:

/^(.+?)\h+-\h+(.+?)(?:\h+(?:ft\.)?\h+(.*?))?\h*(?:\((.*?)\))?\.mp3$/

细分:

  • ^: 字符串开始
  • (.+?):一个或多个字符(非贪婪),捕获为第1组
  • \h+:一个或多个横白-spaces(space,不间断space,...)
  • -:文字连字符
  • \h+:一个或多个横白-spaces(space,不间断space,...)
  • (.+?):一个或多个字符(非贪婪),捕获为第2组
  • (?: )?:可选的,非捕获的,组,它有:
    • \h+:一个或多个横白-spaces(space,不间断space,...)
    • (?:ft\.)?:可选,非捕获文字 ft.
    • \h+:一个或多个横白-spaces(space,不间断space,...)
    • (.*?):零个或多个字符(非贪婪),捕获为组 3
  • \h*:零个或多个水平白色-spaces(space,不间断space,...)
  • (?: )?:可选的,非捕获的,组,它有:
    • \(: 文字 (
    • (.*?):零个或多个字符(非贪婪),捕获为组 4
    • \):文字 )
  • \.mp3: 文字 .mp3
  • $:字符串结尾,所以结合 ^ 整个字符串必须匹配

用在PHP代码中,看起来像这样:

$songs = array(
    'Armin van Buuren - Rain ft. Cathy Burton (Urbanstep Remix).mp3',
    'Alpha Drop - Spring Fever.mp3',
    'Beatcore - Tonight ft. Lynn Boyer.mp3',
    'iru1919 - 天狐.mp3'
);

// Prepare results array
$results = array();
// Define key names that will be used in each element
$keys = array("artist", "songname", "featuring", "remixBy");
// Iterate over input
foreach($songs as $song) {
    if (preg_match(
            "/^(.+?)\h+-\h+(.+?)(?:\h+(?:ft\.)?\h+(.*?))?\h*(?:\((.*?)\))?\.mp3$/", 
            $song, $matches)) {
        // Remove original string (at position 0)
        array_shift($matches);
        // Convert matched items (groups) to associative array
        // and add to result
        $results[] = array_combine($keys, array_pad($matches, 4, ''));
    } else {
        echo "This file name doesn't match the pattern: $song";
    };
}
// Output results:
echo json_encode($results, JSON_PRETTY_PRINT);

输出为:

[
    {
        "artist": "Armin van Buuren",
        "songname": "Rain",
        "featuring": "Cathy Burton",
        "remixBy": "Urbanstep Remix"
    },
    {
        "artist": "Alpha Drop",
        "songname": "Spring Fever",
        "featuring": "",
        "remixBy": ""
    },
    {
        "artist": "Beatcore",
        "songname": "Tonight",
        "featuring": "Lynn Boyer",
        "remixBy": ""
    },
    {
        "artist": "iru1919",
        "songname": "\u5929\u72d0",
        "featuring": "",
        "remixBy": ""
    }
]

变体没有 "Remix"

如果您想从结果中排除单词 "Remix" 本身,那么您可以将正则表达式扩展为:

/^(.+?)\h+\-\h+(.+?)(?:\h+(?:ft\.)?\h+(.*?))?\h*(?:\((.*?)(?:\h+Remix)?\))?\.mp3$/

注意添加的组:

  • (?:\h+Remix)?:一个非捕获的可选组,匹配一个或多个白色space和文字Remix.

使用这种变体,第一首歌曲的输出将作为最后一个键:

"remixBy": "Urbanstep"

PHP 中的完整演练将是:

<?php

$string = 'Armin van Buuren - Rain ft. Cathy Burton (Urbanstep Remix).mp3
Alpha Drop - Spring Fever.mp3
Beatcore - Tonight ft. Lynn Boyer.mp3
iru1919 - 天狐.mp3';

$regex = '~              # delimiter
        ^                # anchors regex to the beginning
        (?<artist>[^-]+) # capture everything but a dash to group "artist"
        -          
        (?<rest>.*)      # capture everything but .mp3 to group "rest"
        (?:\.mp3)
        $
        ~xm';            # multiline and freespace mode
preg_match_all($regex, $string, $matches, PREG_SET_ORDER);
foreach ($matches as $match) {
    $artist = trim($match["artist"]);
    list($title, $artist2) = preg_split("~ft\.~", $match["rest"]);
    echo "Artist: " . trim($artist) . 
        ", Title: " . trim($title) . 
        (!empty($artist2)?", Second Artist: $artist2":"") . 
        "\n";
}
// output:
// Artist: Armin van Buuren, Title: Rain, Second Artist:  Cathy Burton (Urbanstep Remix)
// Artist: Alpha Drop, Title: Spring Fever
// Artist: Beatcore, Title: Tonight, Second Artist:  Lynn Boyer
// Artist: iru1919, Title: 天狐
?>