2010-05-30 3 views
0

파일 이름의 일부를 추출하려면정규식 내가 텍스트 파일과 같은 형식이

나는 일관되게 ****** COMP의 004A7001 번호 20100104 (날짜)에 R을 추출해야
R156484COMP_004A7001_20100104_065119.txt 

및 065119 번호는 신경 쓰지 마라. 문제는 모든 파싱 된 파일이 정확한 명명 규칙을 가지고 있지 않다는 것입니다. 일부는 다음과 같이 할 수 있습니다. (예 004A7001)

R168166CRIT_156B2075_SU2_20091223_123456.txt 

또는

R285476COMP_SU1_125A6025_20100407_123456.txt 

그래서 어떻게 내가 항상 시리얼 것을 얻고, 날짜 (예를 보장하기 위해 대신 분할 regex를 사용할 수 20,100,104.), R ****** COMP (또는 CRIT) ???

내가 지금하는 일은 다음과 같지만 첫 번째 예와 같이 형식이 지정된 파일 만 가져옵니다.

if (file.Count(c => c == '_') != 3) continue; 

하고 더 아래 코드에서 내가 가진 :

string RNumber = Path.GetFileNameWithoutExtension(file); 

string RNumberE = RNumber.Split('_')[0]; 

string RNumberD = RNumber.Split('_')[1]; 

string RNumberDate = RNumber.Split('_')[2]; 

DateTime dateTime = DateTime.ParseExact(RNumberDate, "yyyyMMdd", Thread.CurrentThread.CurrentCulture); 
string cmmDate = dateTime.ToString("dd-MMM-yyyy"); 

업데이트 :에 나는 곳은 지금 - 나는 실제 날짜 형식에 RNumberDate를 구문 분석 오류가 발생합니다. "암시 나는 완전히 문자열을 구문 분석 규칙을 이해하지 못하는 '문자열'

string RNumber = Path.GetFileNameWithoutExtension(file); 

Match RNumberE = Regex.Match(RNumber, @"^(R|L)\d{6}(COMP|CRIT|TEST|SU[1-9])(?=_)", RegexOptions.IgnoreCase); 

Match RNumberD = Regex.Match(RNumber, @"(?<=_)\d{3}[A-Z]\d{4}(?=_)", RegexOptions.IgnoreCase); 
Match RNumberDate = Regex.Match(RNumber, @"(?<=_)\d{8}(?=_)", RegexOptions.IgnoreCase); 



DateTime dateTime = DateTime.ParseExact(RNumberDate, "yyyyMMdd", Thread.CurrentThread.CurrentCulture); 
string cmmDate = dateTime.ToString("dd-MMM-yyyy") 
+0

@jake : 제목에 태그를 넣지 마십시오. –

+0

나는 그것을 기억할 것이다. –

답변

3

여러 정규 표현식을 사용하여이 문제를 해결할 수 있습니다.

compNumber: /^R\d{6}(COMP|CRIT)(?=_)/ 
date:   /(?<=_)\d{8}(?=_)/ 
serialNumber: /(?<=_)\d{3}[A-Z]\d{4}(?=_)/ 

part:   /(?<=_).*?(?=_)/ 

실행 별도로 부분을 당겨하는 캐릭터 라인의 각 정규 표현식.

+0

에릭 J. 아래에 게시 된 정규식 빌더를 사용하여, 이들은 완벽한 표현처럼 보입니다.하지만 한 가지 .. 몇 가지 경우에는 일련 번호가없는 R ###### COMP_TEST_20100103_123456.txt와 같은 형식의 파일이 있습니다 번호. 이 경우 파일을 건너 뛰도록 코드를 어떻게 말할 수 있습니까? –

+0

시리얼이 없다면 이처럼 뭔가를 할 수 없어야합니다. 첫 번째 '_'바로 뒤에 오는 값을 반환하십시오. @? {3} [AZ] \ d {4} (? = _) | (^ _) –

+0

@ jakesankey, 나는 당신이 C# 코드에서 그렇게해야한다고 생각한다. 표현. 상대적으로 간단합니다. 'serialNumber' regexp가 일치하지 않으면 다른 regexp를 실행하십시오. 문자열 분리가 잘 작동하지만 식을 사용하여 답변을 업데이트했습니다. – strager

1

에 유형 'RegularExpressions.Match을'변환 할 수 없습니다 만, 도움이 될 조언은 다음과 같습니다

RegEx.Split에서보세요 및 RegEx.Matches는 정규식을 사용하여 문자열을 나눌 수 있습니다.

당신의 정규식을 만들려면 어떻게해야합니까, 내가 (해당 도구를 사용하면 큰 텍스트 영역에 문자열의 무리를 입력 할 수 있습니다. 예를 들어 일련 번호를 excellent RegEx builder/checker/tutorial을 제안하거나는 어떤) 그리고 RegEx에 대화 형으로 입장하여 현재 일치하는 부분을 확인하십시오. RegEx를 구축하는 방법을 배우는 데 도움이되는 페이지의 오른쪽에있는 "자습서".

1
string filename = "R285476COMP_SU1_125A6025_20100407_123456.txt"; 

Match m = Regex.Match(filename, 
    @"^(R\d+(?:COMP|CRIT))_(?:SU\d+_)?(\d+[A-Z]+\d+)_(?:SU\d+_)?(\d{8})_.*$", 
    RegexOptions.IgnoreCase); 

if (m.Success) 
{ 
    Console.WriteLine(m.Groups[1].Value); // R285476COMP 
    Console.WriteLine(m.Groups[2].Value); // 125A6025 
    Console.WriteLine(m.Groups[3].Value); // 20100407 
} 
+0

C# 코드를 변경하지 않고도 식에서 물건을 이동할 수 있도록 그룹 이름을 지정하는 것이 좋습니다. – strager

+0

+1 나는 답을 위해 이것을 좋아하고, strager를 제안했다. –

관련 문제