2012-12-15 2 views
0

정규 표현식을 사용하여 한꺼번에 많은 파일 이름을 바꾸는 유틸리티를 작성하려고합니다. 한 번에 모두 이름을 바꿀 파일은 특정 명명 규칙을 따릅니다. 이미 파일 이름에있는 데이터를 사용하여 새 명명 규칙으로 변경하려고합니다. 모든 파일이 현재 동일한 규칙을 따르는 것은 아닙니다.런타임시 문자열을 어떻게 구분할 수 있습니까?

그래서 런타임 중에 텍스트 상자에 파일 이름의 패턴을 입력하고 이름을 바꾸기 위해 파일 이름에서 추출 할 토큰을 입력 할 수있는 일반 사용 프로그램을 작성하려고합니다.

예를 들어, [Coalgirls]_Suite_Precure_02_(1280x720_Blu-Ray_FLAC)_[33D74D55].mkv이라는 파일이 하나 있다고 가정합니다. 나는이 내가 바람직 [%group%]_Suite_Precure_%ep%_(...)_[%crc%].mkv에 가깝다 뭔가를 이름을 바꾸기 전에 내 프로그램에 입력 할 수있을 것입니다 의미 Suite Precure - Ep 02 [Coalgirls][33D74D55].mkv

이 파일의 이름을 바꿀 수 있도록하려면 그것은 group, epcrc에서 사용할 로컬 변수를 채우는 것 일괄 이름 바꾸기.

내가 생각하는 특정 프로그램은 파일 이름을 id3 태그로 변환하는 데 사용되는 mp3 태그입니다. 그것은 % artist % - % album % - % tracknumber % - % title %와 같은 것을 넣을 수있게 해주고, 그 4 개의 토큰을 받아 각각의 id3 태그에 넣습니다.

사용자가 정규식 구문을 알 필요없이이 시스템을 어떻게 만들 수 있습니까?

+0

항상 입력 및 출력 예제를 추가하십시오. 1000 % 더 선명 해집니다. –

+0

나는 대답 한 후에 당신이 당신의 질문을 명확히했음을 안다. 도움이되지 않았나요? – usr

+0

@usr 귀하의 답변은 언뜻보기에 CRC를 캡처 할 때 CRC의 정확한 값을 알아야만하는 것처럼 보였습니다. 나는 그것을 읽는 것을 잘못했을 수도있다. – agent154

답변

2

usr에서 언급했듯이 %(?<name>[^%]+)%을 사용하여 검색 문자열의 모든 명명 된 자리 표시자를 추출 할 수 있습니다. 그러면 "그룹", "ep"및 "crc"가 나타납니다.

이제 모든 자리 표시자를 스캔하여 정규식의 각 자리 표시 자에 캡처해야합니다. 위에서 매치를 반복 할 것입니다 (각 자리 매김의 시작 오프셋과 길이를 통해 비 - 자리 표시 자 조각을 탐색 할 수 있습니다).

(귀하의 예제에서 실수가있다, 내가 마지막 부분은 정확하고 내가 (신비를 삭제하고있어 가정합니다 ...))

그것은 다음과 같습니다 정규식 구축 할 것입니다 :

^%(?<group>.*?)_Suite_Precure_(?<ep>.*?)_(?<crc>.*?).mkv$

문제가있는 문자를 올바르게 처리하기 위해 리터럴 조각을 정규식에서 사용하기 전에 Regex.Escape에 전달하십시오.

이제 각 파일 이름에 대해 정규식과 일치 시키려고합니다. 일치하는 경우이 파일의 자리 표시 자 값을 가져옵니다. 그런 다음 해당 자리 표시 자 값을 가져 와서 출력 패턴으로 병합하여 자리 표시자를 바꿉니다. 이것은 당신에게 새로운 이름을주고, 당신은 이름을 바꿀 수 있습니다.

using System; 
using System.Collections.Generic; 
using System.IO; 
using System.Text; 
using System.Text.RegularExpressions; 

namespace renamer 
{ 
    class RenameImpl 
    { 
     public static IEnumerable<Tuple<string,string>> RenameWithPatterns(
      string path, string curpattern, string newpattern, 
      bool caseSensitive) 
     { 
      var placeholderNames = new List<string>(); 

      // Extract all the cur_placeholders from the user's input pattern 
      var input_regex = new Regex(@"(\%[^%]+\%)"); 
      var cur_matches = input_regex.Matches(curpattern); 
      var new_matches = input_regex.Matches(newpattern); 
      var regex_pattern = new StringBuilder(); 

      if (!caseSensitive) 
       regex_pattern.Append("(?i)"); 
      regex_pattern.Append('^'); 

      // Do a pass over the matches and grab info about each capture 
      var cur_placeholders = new List<Tuple<string, int, int>>(); 
      var new_placeholders = new List<Tuple<string, int, int>>(); 
      for (var i = 0; i < cur_matches.Count; ++i) 
      { 
       var m = cur_matches[i]; 
       cur_placeholders.Add(new Tuple<string, int, int>(
        m.Value, m.Index, m.Length)); 
      } 
      for (var i = 0; i < new_matches.Count; ++i) 
      { 
       var m = new_matches[i]; 
       new_placeholders.Add(new Tuple<string, int, int>(
        m.Value, m.Index, m.Length)); 
      } 

      // Build the regular expression 
      for (var i = 0; i < cur_placeholders.Count; ++i) 
      { 
       var ph = cur_placeholders[i]; 

       // Get the literal before the first capture if it is the first 
       if (i == 0 && ph.Item2 > 0) 
        regex_pattern.Append(Regex.Escape(
         curpattern.Substring(0, ph.Item2))); 

       // Generate the capture for the placeholder 
       regex_pattern.AppendFormat("(?<{0}>.*?)", 
        ph.Item1.Replace("%", "")); 

       // The literal after the placeholder 
       if (i + 1 == cur_placeholders.Count) 
        regex_pattern.Append(Regex.Escape(
         curpattern.Substring(ph.Item2 + ph.Item3))); 
       else 
        regex_pattern.Append(Regex.Escape(
         curpattern.Substring(ph.Item2 + ph.Item3, 
         cur_placeholders[i + 1].Item2 - (ph.Item2 + ph.Item3)))); 
      } 

      regex_pattern.Append('$'); 

      var re = new Regex(regex_pattern.ToString()); 

      foreach (var pathname in Directory.EnumerateFileSystemEntries(path)) 
      { 
       var file = Path.GetFileName(pathname); 
       var m = re.Match(file); 

       if (!m.Success) 
        continue; 

       // New name is initially same as target pattern 
       var newname = newpattern; 

       // Iterate through the placeholder names 
       for (var i = new_placeholders.Count; i > 0; --i) 
       { 
        // Target placeholder name 
        var tn = new_placeholders[i-1].Item1.Replace("%", ""); 

        // Get captured value for this capture 
        var ct = m.Groups[tn].Value; 

        // Perform the replacement 
        newname = newname.Remove(new_placeholders[i - 1].Item2, 
         new_placeholders[i - 1].Item3); 
        newname = newname.Insert(new_placeholders[i - 1].Item2, ct); 
       } 

       newname = Path.Combine(path, newname); 
       yield return new Tuple<string, string>(pathname, newname); 
      } 
     } 
    } 
} 
+0

이것은 usr의 응답보다 많은 도움이되지는 않지만 혼란이 어디에 있는지 알 수 있다고 생각합니다. % group %, % ep % 등과 같은 일반적인 토큰 자리 표시자를 만들고 싶습니다. 사용자가 원시 정규식 구문을 사용하지 않도록하고 싶습니다. 내가 생각하는 한가지 특별한 프로그램은 파일 이름을 id3 태그로 변환하는 데 사용되는 mp3 태그입니다. 그것은 % artist % - % album % - % tracknumber % - % title %와 같은 것을 넣을 수있게 해주고, 그 4 개의 토큰을 받아 각각의 id3 태그에 넣습니다. 어떻게하면 사용자가 정규식 구문을 알지 않고도 이와 비슷한 시스템을 만들 수 있습니까? – agent154

+0

사용자는 정규식 구문을 알 필요가 없습니다. 단순히 placeholder [group] [crc] 등에서 정규 표현식을 생성하고 중간에 리터럴 텍스트를 생성합니다. 예를 들어, [Album] - [Artist] - [Title] .mp3은 [Title] ([Album], [Artist])입니다. 이것이 바로 사용자가 할 일입니다. 이것은 [A] - [B] - [C] .mp3가 [C] ([A], [B])가됩니다. mp3. 정규 표현식을 생성하고 사용자의 자리 표시자를 (? . *?)로 바꾸면 정규 표현식이 문자열의 해당 부분을 추출하고 그룹 배열에 이름 "name"을 부여합니다. – doug65536

+0

내 예제에서 "-"및 "-"및 ".mp3"은 리터럴 텍스트 부분이며, 정규식 일치 항목은 현재 파일 이름이 해당 부분에있는 내용을 추출합니다. – doug65536

1

정규 표현식 패턴 %(?<name>[^%]+)%을 만드십시오. 이렇게하면 퍼센트 기호로 둘러싸인 문자열의 모든 토큰을 얻을 수 있습니다.

그런 다음, 그들을 대체 할 Regex.Replace를 사용

var replaced = Regex.Replace(input, pattern, (Match m) => EvaluateToken(m.Groups["name"].Value)); 

Regex.Replace는 동적 가치를 제공 할 수있는 콜백을 취할 수 있습니다.

+0

이것은 내가 이미 알고있는 값에 대해서만 작동 할 것 같은데 ... 다른 파일 이름에 다양한 CRC 값을 캡처 할 수 있습니까? 원래 게시물에 편집 한 예를 참조하십시오 ... – agent154

+0

이제 알겠습니다. 사용자가 관심있는 값 (예 : CRC)을 명명 된 그룹으로 캡처하는 정규식을 입력하게 할 수 있습니까? – usr

+0

문제는이 패턴에 따라 일괄 적으로 이름이 바뀌도록 여러 파일을 공급하려고합니다. 원래 패턴에 맞게 24 개 이상의 파일 이름을 가질 수 있으므로 한 번에 모두 올바르게 이름을 바꿔야합니다. – agent154

관련 문제