2010-03-19 6 views
4

입력 문자열에 "a -> b, c, d"패턴을 찾으려고합니다. 내가 사용하고 패턴은은 다음과 같다 :EOL 특수 문자가 일치하지 않음

"^[ \t]*(\\w+)[ \t]*->[ \t]*(\\w+)((?:,[ \t]*\\w+)*)$" 

이 패턴은 C#을 패턴은 "\의 t"는 표를 말한다 (그 하나의 탈출 litteral은 .NET 문자열 API에 의해 해석하여)의 "\ w"는 잘 알려진 regex litteral 미리 정의 된 클래스를 가리키며, .NET STring API에 의해 "\ w"로 해석되도록 이중 이스케이프 처리 된 다음 .NET Regex API에 의해 "단어 클래스"로 해석됩니다.

입력은 :

a -> b 
b -> c 
c -> d 

함수이다

private void ParseAndBuildGraph(String input) { 
    MatchCollection mc = Regex.Matches(input, "^[ \t]*(\\w+)[ \t]*->[ \t]*(\\w+)((?:,[ \t]*\\w+)*)$", RegexOptions.Multiline); 
    foreach (Match m in mc) { 
     Debug.WriteLine(m.Value); 
    } 
} 

출력은 : 실제로

c -> d 

, "$"를 종료 선에 문제가 특수 숯. "$"앞에 "\ r"을 삽입하면 작동하지만, "$"는 여러 줄 끝과 (여러 줄 옵션과) 일치합니다 (특히 Windows 환경에서는 \ r \ n). 그렇지 않은가?

답변

7

(탈출해야 할 유일한 것은 """에있다). .NET regexes에서 $줄 구분 기호 앞에 일치하지 않으므로 줄 넘김 - 문자 \n 앞에 일치합니다. 이 동작은 Perl의 정규 표현식과 일치하지만 내 생각에는 여전히 잘못되었습니다. According to the Unicode standard, $는의 전에 일치해야합니다 :

\n, \r\n, \r, \x85, \u2028, \u2029, \v 또는

\f ... 그리고 결코 \r\n 사이에 일치합니다. Java는 그 언어 (\v\f 제외)를 따르지만, Java 후에 오랫동안 나왔고 적어도 유니 코드 지원이 Java만큼 우수하다는 .NET은 \n만을 인식합니다. Microsoft가 해당 행 분리 기호와 얼마나 강하게 연관되어 있는지를 고려할 때 적어도 \r\n을 올바르게 처리 할 것이라고 생각할 수 있습니다. 은 (만일 Singleline 모드가 설정되어 있지 않으면) \n 일치하지 않지만, 일치 \r을 수행 :

.이 같은 패턴을 따른다주의하십시오. 정규식에 \w+ 대신 .+을 사용한 경우이 문제를 알지 못했을 수 있습니다. 캐리지 리턴이 일치 항목에 포함되지만 결과를 인쇄 할 때 콘솔에서 무시하게됩니다.

편집 : 결과에 캐리지 리턴을 포함시키지 않고 캐리지 리턴을 허용하려는 경우 앵커를 다음과 같이 바꿀 수 있습니다 : (?=\r?\n.

+1

+1 믿을 수가 없어 ... –

+0

답장을 보내 주셔서 감사합니다. 그리고 실제로 그것은 놀라운 결론입니다. –

+0

c/C++에서 O_BINARY 플래그와 같은 데이터를 시스템이 일치하도록 설정할 수있는 플래그가 있는지 궁금합니다. – Dave

1

\t을 정규식 \t 또는 C# \t으로 사용 하시겠습니까? 나는 항상 정규식 그대로 문자열 리터럴을 사용

@"^[ \t]*(\w+)[ \t]*->[ \t]*(\w+)(,[ \t]*\w+)*$" 

이도 나를 놀라게

+0

실제로 \ t는 표를 나타냅니다. 공백 문자에 \\ s를 사용하고 싶지는 않습니다. 왜냐하면 사용자가 줄 끝 문자를 입력하는 것을 원하지 않기 때문에 공백과 도표 만 허용됩니다. 그러나 내 질문은 단순화 된 패턴 "^ (\\ w +) -> (\\ w +) ((: \, \\ w +) *) $"와 동일하게 유지됩니다. 원래의 질문을 업데이트했습니다. –

+0

@ Aurélien - 그렇습니다.하지만 축 어적 문자열 리터럴이 없으면 정규 표현식에서 * all *에'\ t'이 표시되지 않습니다.

+0

@Marc Gravell - 정규식이 내장 탭을 허용하지 않는 한 탭 또는 공백 옵션입니다. \ t – Guvante

1

일반적으로 C, C++, C#에서 프로그램 내의 문자열은 줄 구분 기호로 "\ n"을 사용합니다. 텍스트 모드 변환이 켜져 있으면 "\ r \ n"은 I/O 레이어에만 나타납니다.

+0

좋은 지적. 드물게이 문제가 어떻게 발생하는지 항상 저에게 놀라움을 금치 못했습니다. 하지만 여전히 유니 코드 표준에 부적합하다고 잘못 생각합니다. –

+0

\ r \ n은 Microsoft 회선 종료입니다. 예를 들어, Notepad.exe는 "\ n"종료를 인식하지 않고 "\ r \ n"만 인식합니다. Unix 사용자의 경우 "\ n"이 일반 회선 종결 문자이며 Mac 사용자의 경우 "\ r"이 사용됩니다. 바보 같은 엉망이야? 동의합니다 :-) –

+0

\ r \ n은 텍스트 파일의 줄 종결 자입니다 (Windows의 경우). \ n은 코드의 종결 자입니다. I/O 레이어는 파일을 "텍스트 모드"로 열 때만 변환됩니다. –

관련 문제