0

映画名から特定の文字列を削除するためにC#正規表現を使用しようとして失敗しました。

私が使用しているファイル名の例は次のとおりです。

EuroTrip(2004)[SD]

イベントホライゾン(1997)[720]

ワイルドスピード(2009)[1080p]

スタートレック(2009)[不明]

角かっこまたはかっこ内のもの(角かっこ自体を含む)をすべて削除したい

これまで私が使用しているもの:

movieTitleToFetch = Regex.Replace(movieTitleToFetch, "([*\\(\\d{4}\\)])", "");

これで年と括弧は削除されたようですが、他の部分に影響を与えずに角かっことコンテンツを削除する方法がわかりません...さまざまな結果が得られましたが、最も近い結果は次のとおりです。

movieTitleToFetch = Regex.Replace(movieTitleToFetch, "([?\\[+A-Z+\\]])", "");

それは私に残しました:

urorip(2004)

それ以外の:

EuroTrip(2004)[SD]

実行するだけなので、最後に残っている空白はすべて問題ありません

movieTitleToFetch = movieTitleToFetch.Trim();

最後に。

前もって感謝します、

アレックス

4

7 に答える 7

3

この正規表現パターンは問題なく機能するはずです...多分少し調整が必要です

"[\[\(].+?[\]\)]"

Regex.Replace(movieTitleToFetch, @"[\[\(].+?[\]\)]", "");

これは、「[」または「(」から次の「]」または「)」までのいずれかに一致する必要があります。

それでも問題が解決しない場合は、括弧のエスケープ文字を削除してみてください。

Regex.Replace(movieTitleToFetch, @"[\[(].+?[\])]", "");
于 2011-02-15T12:28:29.640 に答える
1

@Craigtはかなり適切ですが、角かっこが一致していることを確認する方がおそらくクリーンです。

([\[].*?[\]]|[\(].*?[\)]) 
于 2011-02-15T12:33:27.033 に答える
1

私はこのスレッドに遅れていることを知っていますが、ダウンロードした映画のファイル名をサニタイズするための簡単なアルゴリズムを作成しました。

これにより、次の手順が実行されます。

  1. 括弧内のすべてを削除します(年が見つかった場合は情報を保持しようとします)
  2. 一般的に使用される単語のリストを削除します(720p、bdrip、h264など...)
  3. それがタイトルの言語情報である可能性があると想定し、残りの文字列の最後(特別な単語の前)でそれらを削除します
  4. 括弧内に年が見つからなかった場合は、残りの文字列の終わりを確認します(言語の場合)

これを行うと、ドットとスペースが置き換えられるため、たとえば、タイトルを検索APIのクエリとして使用できるようになります。

これがXUnitでのテストです(私はほとんどのイタリア語のタイトルを使用してテストしました)

using Grappachu.Movideo.Core.Helpers.TitleCleaner;
using SharpTestsEx;
using Xunit;

namespace Grappachu.MoVideo.Test
{
    public class TitleCleanerTest
    {
        [Theory]
        [InlineData("Avengers.Confidential.La.Vedova.Nera.E.Punisher.2014.iTALiAN.Bluray.720p.x264 - BG.mkv",
            "Avengers Confidential La Vedova Nera E Punisher", 2014)]
        [InlineData("Fuck You, Prof! (2013) BDRip 720p HEVC ITA GER AC3 Multi Sub PirateMKV.mkv",
            "Fuck You, Prof!", 2013)]
        [InlineData("Il Libro della Giungla(2016)(BDrip1080p_H264_AC3 5.1 Ita Eng_Sub Ita Eng)by siste82.avi",
            "Il Libro della Giungla", 2016)]
        [InlineData("Il primo dei bugiardi (2009) [Mux by Little-Boy]", "Il primo dei bugiardi", 2009)]
        [InlineData("Il.Viaggio.Di.Arlo-The.Good.Dinosaur.2015.DTS.ITA.ENG.1080p.BluRay.x264-BLUWORLD",
            "il viaggio di arlo", 2015)]
        [InlineData("La Mafia Uccide Solo D'estate 2013 .avi",
            "La Mafia Uccide Solo D'estate", 2013)]
        [InlineData("Ip.Man.3.2015.iTA.AC3.5.1.448.Chi.Aac.BluRay.m1080p.x264.Sub.[scambiofile.info].mkv",
            "Ip Man 3", 2015)]
        [InlineData("Inferno.2016.BluRay.1080p.AC3.ITA.AC3.ENG.Subs.x264-WGZ.mkv",
            "Inferno", 2016)]
        [InlineData("Ghostbusters.2016.iTALiAN.BDRiP.EXTENDED.XviD-HDi.mp4",
            "Ghostbusters", 2016)]
        [InlineData("Transcendence.mkv", "Transcendence", null)]
        [InlineData("Being Human (Forsyth, 1994).mkv", "Being Human", 1994)]
        public void Clean_should_return_title_and_year_when_possible(string filename, string title, int? year)
        {
            var res = MovieTitleCleaner.Clean(filename);

            res.Title.ToLowerInvariant().Should().Be.EqualTo(title.ToLowerInvariant());
            res.Year.Should().Be.EqualTo(year);
        }
    }
}

および最初のバージョンのコード

using System;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions; 

namespace Grappachu.Movideo.Core.Helpers.TitleCleaner
{
    public class MovieTitleCleanerResult
    {
        public string Title { get; set; }
        public int? Year { get; set; }
        public string SubTitle { get; set; }
    }

    public class MovieTitleCleaner
    {
        private const string SpecialMarker = "§=§";
        private static readonly string[] ReservedWords;
        private static readonly string[] SpaceChars;
        private static readonly string[] Languages;

        static MovieTitleCleaner()
        {
            ReservedWords = new[]
            {
                SpecialMarker, "hevc", "bdrip", "Bluray", "x264", "h264", "AC3", "DTS", "480p", "720p", "1080p"
            };
            var cultures = CultureInfo.GetCultures(CultureTypes.AllCultures);
            var l = cultures.Select(x => x.EnglishName).ToList();
            l.AddRange(cultures.Select(x => x.ThreeLetterISOLanguageName));
            Languages = l.Distinct().ToArray();


            SpaceChars = new[] {".", "_", " "};
        }


        public static MovieTitleCleanerResult Clean(string filename)
        {
            var temp = Path.GetFileNameWithoutExtension(filename);
            int? maybeYear = null;

            // Remove what's inside brackets trying to keep year info.
            temp = RemoveBrackets(temp, '{', '}', ref maybeYear);
            temp = RemoveBrackets(temp, '[', ']', ref maybeYear);
            temp = RemoveBrackets(temp, '(', ')', ref maybeYear);

            // Removes special markers (codec, formats, ecc...)
            var tokens = temp.Split(SpaceChars, StringSplitOptions.RemoveEmptyEntries);
            var title = string.Empty;
            for (var i = 0; i < tokens.Length; i++)
            {
                var tok = tokens[i];
                if (ReservedWords.Any(x => string.Equals(x, tok, StringComparison.OrdinalIgnoreCase)))
                {
                    if (title.Length > 0)
                        break;
                }
                else
                {
                    title = string.Join(" ", title, tok).Trim();
                }
            }
            temp = title;

            // Remove languages infos when are found before special markers (should not remove "English" if it's inside the title)
            tokens = temp.Split(SpaceChars, StringSplitOptions.RemoveEmptyEntries);
            for (var i = tokens.Length - 1; i >= 0; i--)
            {
                var tok = tokens[i];
                if (Languages.Any(x => string.Equals(x, tok, StringComparison.OrdinalIgnoreCase)))
                    tokens[i] = string.Empty;
                else
                    break;
            }
            title = string.Join(" ", tokens).Trim();


            // If year is not found inside parenthesis try to catch at the end, just after the title
            if (!maybeYear.HasValue)
            {
                var resplit = title.Split(SpaceChars, StringSplitOptions.RemoveEmptyEntries);
                var last = resplit.Last();
                if (LooksLikeYear(last))
                {
                    maybeYear = int.Parse(last);
                    title = title.Replace(last, string.Empty).Trim();
                }
            }


            // TODO: review this. when there's one dash separates main title from subtitle 
            var res = new MovieTitleCleanerResult();
            res.Year = maybeYear;
            if (title.Count(x => x == '-') == 1)
            {
                var sp = title.Split('-');
                res.Title = sp[0];
                res.SubTitle = sp[1];
            }
            else
            {
                res.Title = title;
            }


            return res;
        }

        private static string RemoveBrackets(string inputString, char openChar, char closeChar, ref int? maybeYear)
        {
            var str = inputString;
            while (str.IndexOf(openChar) > 0 && str.IndexOf(closeChar) > 0)
            {
                var dataGraph = str.GetBetween(openChar.ToString(), closeChar.ToString());
                if (LooksLikeYear(dataGraph))
                {
                    maybeYear = int.Parse(dataGraph);
                }
                else
                {
                    var parts = dataGraph.Split(SpaceChars, StringSplitOptions.RemoveEmptyEntries);
                    foreach (var part in parts)
                        if (LooksLikeYear(part))
                        {
                            maybeYear = int.Parse(part);
                            break;
                        }
                }
                str = str.ReplaceBetween(openChar, closeChar, string.Format(" {0} ", SpecialMarker));
            }
            return str;
        }

        private static bool LooksLikeYear(string dataRound)
        {
            return Regex.IsMatch(dataRound, "^(19|20)[0-9][0-9]");
        }
    }


    public static class StringUtils
    {
        public static string GetBetween(this string src, string a, string b,
            StringComparison comparison = StringComparison.Ordinal)
        {
            var idxStr = src.IndexOf(a, comparison);
            var idxEnd = src.IndexOf(b, comparison);
            if (idxStr >= 0 && idxEnd > 0)
            {
                if (idxStr > idxEnd)
                    Swap(ref idxStr, ref idxEnd);
                return src.Substring(idxStr + a.Length, idxEnd - idxStr - a.Length);
            }
            return src;
        }

        private static void Swap<T>(ref T idxStr, ref T idxEnd)
        {
            var temp = idxEnd;
            idxEnd = idxStr;
            idxStr = temp;
        }

        public static string ReplaceBetween(this string s, char begin, char end, string replacement = null)
        {
            var regex = new Regex(string.Format("\\{0}.*?\\{1}", begin, end));
            return regex.Replace(s, replacement ?? string.Empty);
        }
    }
}
于 2017-09-06T17:49:17.987 に答える
0

代わりにこれを使用することはできません:-

if(movieTitleToFetch.Contains("("))
         movieTitleToFetch=movieTitleToFetch.Substring(0,movieTitleToFetch.IndexOf("("));

上記のコードは、これらの文字列に最適な映画のタイトルを確実に返します:-

EuroTrip(2004)[SD]

イベントホライゾン(1997)[720]

ワイルドスピード(2009)[1080p]

スタートレック(2009)[不明]

年がなく、タイプするだけの場合が発生した場合:-

EuroTrip [SD]

事象の地平線[720]

ワイルドスピード[1080p]

スタートレック[不明]

次にこれを使用します

if(movieTitleToFetch.Contains("("))
         movieTitleToFetch=movieTitleToFetch.Substring(0,movieTitleToFetch.IndexOf("("));
else if(movieTitleToFetch.Contains("["))
         movieTitleToFetch=movieTitleToFetch.Substring(0,movieTitleToFetch.IndexOf("["));
于 2011-02-15T12:31:12.240 に答える
0

これはトリックを行います:

@"(\[[^\]]*\])|(\([^\)]*\))"

「[」から次の「]」まで、および「(」から次の「)」までのすべてを削除します。

于 2011-02-15T12:33:11.073 に答える
0

あなたはただ使うことができます:

string MovieTitle="Star Trek (2009) [Unknown]";
movieTitleToFetch= MovieTitle.IndexOf('(')>MovieTitle.IndexOf('[')?
                    MovieTitle.Substring(0,MovieTitle.IndexOf('[')):
                    MovieTitle.Substring(0,MovieTitle.IndexOf('('));
于 2011-02-15T12:33:59.730 に答える
0

私はあなたの例のいずれかに一致するものを思いつきました.+\s(?<year>\(\d{4}\))\s(?<format>\[\w+\])、そしてあなたがそれらを置き換えるのを助けるために名前付きのキャプチャグループとして年とフォーマットを含みます。

このパターンは次のように解釈されます。

任意の文字、1つ以上の繰り返し
Whitespace
Literal'('、4桁の数字、リテラル')'(年)
Whitespace
Literal'['、英数字、1つ以上の繰り返し、文字']'(形式)

于 2011-02-15T12:39:55.087 に答える