C#에서 텍스트 파일을 구문 분석하는 가장 좋은 방법은 무엇입니까?
문제
다음과 같이 구성 파일을 구문 분석하고 싶습니다.
[KEY:Value]
[SUBKEY:SubValue]
이제 나는 StreamReader
, 라인을 문자 배열로 변환하는 중 더 나은 방법이 있을 것이라고 생각했습니다.그래서 나는 겸손한 독자 여러분에게 도움을 요청합니다.
한 가지 제한 사항은 Linux/Mono 환경(정확히는 1.2.6)에서 작동해야 한다는 것입니다.최신 2.0 릴리스(Mono)가 없으므로 언어 기능을 C# 2.0 또는 C# 1.0으로 제한해 보세요.
해결책
고려했지만 XML을 사용하지 않을 것입니다.나는 이 내용을 손으로 작성할 예정인데, XML을 손으로 편집하면 머리가 아프게 됩니다.:')
봤어? YAML?
모든 어려움 없이 XML의 이점을 얻을 수 있습니다.구성 파일, 미리 준비된 데이터베이스 데이터 등과 같은 작업을 위해 Ruby 커뮤니티에서 광범위하게 사용됩니다.
여기에 예가 있습니다
customer:
name: Orion
age: 26
addresses:
- type: Work
number: 12
street: Bob Street
- type: Home
number: 15
street: Secret Road
다음이 있는 것으로 보입니다. C# 라이브러리는 여기, 나는 개인적으로 사용하지 않았지만 Yaml은 매우 간단하므로 "얼마나 힘들 수 있습니까?" :-)
나는 자신만의 임시 형식을 만드는 것(그리고 파서 버그를 다루는 것)보다 이것이 더 낫다고 말하고 싶습니다.
다른 팁
나는 지난번에 거의 이 정확한 문제를 보고 있었습니다. 이 기사 문자열 토큰화는 정확히 필요한 것입니다.토큰을 다음과 같이 정의하고 싶을 것입니다:
@"(?<level>\s) | " +
@"(?<term>[^:\s]) | " +
@"(?<separator>:)"
기사는 그것을 설명하는 데 꽤 좋은 역할을 합니다.거기에서 적절하다고 생각되는 대로 토큰을 먹기 시작합니다.
유용한 팁:대한 LL(1) 파서 (읽다:쉬움) 토큰은 접두사를 공유할 수 없습니다.당신이 가지고 있다면 abc
토큰으로는 ace
토큰으로
메모:이 기사는 | 그 예에서 캐릭터를 던지십시오.
있다 .NET용 또 다른 YAML 라이브러리 개발중인 것입니다.현재는 YAML 스트림 읽기를 지원하며 Windows 및 Mono에서 테스트되었습니다.쓰기 지원은 현재 구현 중입니다.
라이브러리를 사용하는 것은 거의 항상 자신만의 라이브러리를 사용하는 것보다 바람직합니다.다음은 나중에 당신을 괴롭히게 될 "아, 난 절대 필요하지 않을 거야/그건 생각하지 않았어"에 대한 간단한 목록입니다.
- 이스케이프 문자.원하는 경우:키에 ]가 있나요? 아니면 값에 ]가 있나요?
- 이스케이프 문자를 이스케이프합니다.
- 유니코드
- 탭과 공백의 혼합(Python의 공백 구분 구문 문제 참조)
- 다양한 반환 문자 형식 처리
- 구문 오류 보고 처리
다른 사람들이 제안한 것처럼 YAML이 최선의 선택인 것 같습니다.
스택을 사용하고 푸시/팝 알고리즘을 사용할 수도 있습니다.이것은 열기/닫기 태그와 일치합니다.
public string check()
{
ArrayList tags = getTags();
int stackSize = tags.Count;
Stack stack = new Stack(stackSize);
foreach (string tag in tags)
{
if (!tag.Contains('/'))
{
stack.push(tag);
}
else
{
if (!stack.isEmpty())
{
string startTag = stack.pop();
startTag = startTag.Substring(1, startTag.Length - 1);
string endTag = tag.Substring(2, tag.Length - 2);
if (!startTag.Equals(endTag))
{
return "Fout: geen matchende eindtag";
}
}
else
{
return "Fout: geen matchende openeningstag";
}
}
}
if (!stack.isEmpty())
{
return "Fout: geen matchende eindtag";
}
return "Xml is valid";
}
파일의 내용을 읽을 수 있도록 조정할 수도 있습니다.정규 표현식도 좋은 생각입니다.
비교적 쉽게 정보를 읽고 저장할 수 있는 .NET 클래스가 이미 있으므로 XML 기반 구성 파일을 사용하는 것이 더 나을 것 같습니다.이것이 불가능한 이유가 있습니까?
@남자 이름: XML을 직접 편집하는 것이 지루한 것은 사실이지만, 여러분이 제시하는 구조는 이미 XML과 매우 유사해 보입니다.
그렇다면 좋은 방법이 있습니다.
@기슈
실제로 이스케이프 문자를 수용한 후에 내 정규식은 내 손으로 작성한 하향식 재귀 파서보다 약간 느리게 실행되었으며 이는 중첩(하위 항목을 상위 항목에 연결) 및 손으로 쓴 파서 보고 오류가 없었습니다.
정규 표현식은 작성 속도가 약간 더 빨랐지만(비록 수동 파서에 대한 경험이 약간 있음) 오류 보고 기능이 좋지 않습니다.이를 추가하면 수행하기가 약간 더 어려워지고 길어집니다.
또한 손으로 쓴 파서가 의도를 더 쉽게 이해할 수 있다고 생각합니다.예를 들어 다음은 코드 조각입니다.
private static Node ParseNode(TextReader reader)
{
Node node = new Node();
int indentation = ParseWhitespace(reader);
Expect(reader, '[');
node.Key = ParseTerminatedString(reader, ':');
node.Value = ParseTerminatedString(reader, ']');
}
지속되는 형식에 관계없이 Regex를 사용하는 것이 가장 빠른 구문 분석 방법입니다.Ruby에서는 아마도 몇 줄의 코드일 것입니다.
\[KEY:(.*)\]
\[SUBKEY:(.*)\]
이 두 가지는 첫 번째 그룹의 Value 및 SubValue를 가져옵니다.문자열과 정규식을 일치시키는 방법에 대해서는 MSDN을 확인하세요.
이것은 모든 사람이 고양이에게 가지고 있어야 할 것입니다.정규식 이전 시대는 빙하 시대처럼 보일 것입니다.