简体   繁体   English

如何在 PHP 中使用多个模式获取字符串的一部分? [答案:使用正则表达式,但究竟如何?]

[英]How to get parts of a string using multiple patterns in PHP? [Answer: Use a regular expression, but how exactly?]

I know there are similar questions, (this one " How do you use a variable in a regular expression? " seems to be close), but I want to know (the best way) how to fix my problem.我知道有类似的问题,(这个“ 你如何在正则表达式中使用变量? ”似乎很接近),但我想知道(最好的方法)如何解决我的问题。

I have some patterns defined which I use to detect an artist and a title in some file names (of MP3 and other audio files).我定义了一些模式,用于检测某些文件名(MP3 和其他音频文件)中的艺术家和标题。 It is similar the way MP3tag (a well known Windows application) converts filenames into MP3 tags.它类似于 MP3tag(一个众所周知的 Windows 应用程序)将文件名转换为 MP3 标签的方式。 How to do this?这个怎么做?

Below a small test application.下面是一个小测试应用程序。 (Negative cases are missing, but you get the grip.) (没有负面案例,但你掌握了。)

<?php

define('SEARCHPATTERNS', array(
    '%track%. %artist% - %title%',
    '%track% - %artist% - %title%',
    '%track%. %title%',
    '%track% - %title%',
    '%title%'));

define('UNKNOWN_ARTIST_TITLE_ARRAY', array('?', '?'));

$fileNames = array(
    '0780. Janis Joplin - Mercedes Benz.mp3',
    '0780. Janis Joplin - Mercedes Benz.flac',

    '0780 - Janis Joplin - Mercedes Benz.mp3',
    '0780 - Janis Joplin - Mercedes Benz.flac',

    '0780. Mercedes Benz.mp3',
    '0780. Mercedes Benz.flac',

    '0780 - Mercedes Benz.mp3',
    '0780 - Mercedes Benz.flac',

    'Mercedes Benz.mp3',
    'Mercedes Benz.flac',
);

//Test some file names 
foreach($fileNames as $fileName)
{
    $titleAndArtist = GetTitleArtistUsingSearchPattern($fileName);
    var_dump($titleAndArtist);    
}

function GetTitleArtistUsingSearchPattern($fileName)
{
    foreach(SEARCHPATTERNS as $pattern)
    {
        $artist = '???????????'; //  Get it from fileName if it matches the pattern, but how?
        $title = '???????????'; //  Get it from fileName if it matches the pattern, but how?

        if(true) // If is matches.... How?
        {
            return array(
                empty($artist) ? UNKNOWN_ARTIST_TITLE_STRINGS[0] : $artist,
                empty($title) ? UNKNOWN_ARTIST_TITLE_STRINGS[1] : $title
            );
        } 
    }

    return UNKNOWN_ARTIST_TITLE_ARRAY;    

}

?>

I am quite sure I have to use a regular expression search (regex) for this.我很确定我必须为此使用正则表达式搜索(regex)。 I cannot think clearly right now (thanks to Corona).我现在无法清楚地思考(感谢 Corona)。 Help me out please.请帮帮我。 Very much appreciated!非常感谢!

I did something like this before for a script that helped me tag my music collection.我之前为帮助我标记我的音乐收藏的脚本做过类似的事情。 I used Named Capturing Groups .我使用了命名捕获组

You just need to define the patterns that will match the different parts of the file inside the structure: (?P<name>pattern) .您只需要定义将匹配结构内文件不同部分的模式: (?P<name>pattern) Where name is a tag that describes the pattern.其中name是描述模式的标签。

Example:例子:

$patterns = [
  //This will match `00. artist - title.ext`
  '/(?P<track>[0-9]{2})\.\s(?P<artist>.+)\s-\s(?P<title>.+)\.([a-z0-9]{3,4})/i',
  //This will match `00. title.ext`
  '/(?P<track>[0-9]{2})\.\s(?P<title>.+)\.([a-z0-9]{3,4})/i',
  //This will match `artist - album - 00 title.ext`
  '/(?P<artist>.+)\s-\s(?P<album>.+)\s-\s(?P<track>[0-9]{2})\s(?P<title>.+)\.[a-z0-9]{3,4}/i'

  // and so on...
];

$filename = "01. Cool Band - Song Title.flac";
$matches = [];
foreach($patterns as $pattern) {
  preg_match($pattern, $filename, $matches);

  //Matched artist?
  $artist = $matches['artist'] ?? false;

  //Matched song title?
  $title = $matches['title'] ?? false;

  //Matched album?
  $album = $matches['album'] ?? false;

  //etc...
}

The solution is basically what David Gomez suggested.解决方案基本上是大卫戈麦斯建议的。 Works like a charm.奇迹般有效。 I can't imagine their are many other good solutions for this particular problem.我无法想象他们对于这个特定问题还有许多其他好的解决方案。 Here's my implementation (part of a class):这是我的实现(类的一部分):

private function GetTrackInfoFromFileName($fileName, &$item,  $defaultValue = '?')
{
    $patterns = array(          
        '/(?P<track>\d{1,4})\.\s(?P<artist>.+)\s-\s(?P<title>.+)\.([a-z0-9]{3,4})/i', //Matches `0000. artist - title.ext`
        '/(?P<track>\d{1,4})\s-\s(?P<artist>.+)\s-\s(?P<title>.+)\.([a-z0-9]{3,4})/i', //Matches `0000 - artist - title.ext`
        '/(?P<artist>.+)\s-\s(?P<title>.+)\.([a-z0-9]{3,4})/i', //Matches `artist - title.ext`
        '/(?P<track>\d{1,4})\.\s(?P<title>.+)\.([a-z0-9]{3,4})/i', //Matches `0000. title.ext`
    ); 

    $matches = [];

    foreach($patterns as $pattern)
    {
        preg_match($pattern, $fileName, $matches);
        if(empty($matches))
        {
            continue;
        }
        $item['artist'] = $matches['artist'] ?? $defaultValue;
        $item['title'] = $matches['title']  ?? $defaultValue;
        $item['track'] = isset($matches['track']) ? array($matches['track']) : array($defaultValue);
        return;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在PHP中使用正则表达式提取零件? - How to extract parts using regular expression in PHP? 如何在PHP中使用正则表达式获取注释字符串? - How to get commented string using regular expression in PHP? 如何使用php中的正则表达式从字符串中获取值 - how to get value from a string using regular expression in php 如何在PHP中使用正则表达式获取日期字符串位置 - How to get date string position using regular expression in PHP 正则表达式以匹配Php中的多个模式 - Regular Expression to match multiple patterns in Php PHP:如何在PHP中使用正则表达式将字符串拆分为2 - PHP: How to use Regular Expression in PHP to Split String in 2 在php中,如何使用正则表达式捕获两个模式之间的所有内容(以及每个模式的最短实例)? - In php, how can I use a regular expression to capture everything between two patterns (and the shortest instance of each pattern)? 如何匹配包含任意字符串的正则表达式,并使用PHP仅将该任意字符串转换为变量? - How to match a regular expression that contains an arbitrary string, and get only that arbitrary string into a variable using PHP? 如何正确转义字符串以在PHP中使用正则表达式? - How to properly escape a string for use in regular expression in PHP? 正则表达式字边界在 PHP 中究竟是如何工作的? - How exactly do Regular Expression word boundaries work in PHP?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM