대신 메모리에 전체 파일을로드하고 그 위에 정규식을 실행하는 것보다 메모리 문제없이 모든 크기의 파일을 처리하는 빠른 방법은 다음과 같습니다
open System
open System.IO
open System.Text.RegularExpressions
// regex: beginning of line, followed by optional whitespace,
// followed by comment chars.
let reComment = Regex(@"^\s*//", RegexOptions.Compiled)
let stripComments infile outfile =
File.ReadLines infile
|> Seq.filter (reComment.IsMatch >> not)
|> fun lines -> File.WriteAllLines(outfile, lines)
stripComments "input.txt" "output.txt"
출력 파일을해야합니다 입력 파일을 읽는 동안 출력에 쓰고 있기 때문에 입력 파일과 다를 수 있습니다. 우리는 정규식을 사용하여 주석 줄 (선택적 선행 공백 포함)을 식별하고 Seq.filter
을 사용하여 주석 줄이 출력 파일로 보내지지 않도록합니다.
전체 입력 또는 출력 파일을 메모리에 보유하지 않으므로이 함수는 모든 크기의 파일에서 작동하며 "전체 파일 읽기, 전체 정규식 쓰기, 전체 파일 쓰기"접근보다 빠릅니다.
위험은 앞서
이 코드는 같은 줄에 몇 가지 코드 뒤에 표시 주석을 제거하지 않습니다. 그러나 정규 표현식은 해당 작업에 적합한 도구가 아닙니다. 다음 두 줄의 코드를 구분할 수있는 정규 표현식을 사용하고 파일에서 정규 표현식과 일치하는 모든 것을 제거 할 때 첫 번째 표현식을 손상시키지 않는 한 :
let request = WebRequest.Create("http://foo.com")
let request = WebRequest.Create(inputUrl) // this used to be hard-coded
당신이 다루는 제약 조건을 모르지만 RegEx를 사용해야하는 상황을 상상할 수 없습니다. 귀하의 경우, .StartsWith를 사용하여 각 문자열을 테스트하는 것이 더 간단하고 안전합니다. 당신을 후원하는 사람들이 유지하기가 훨씬 쉬울 것입니다. 내가 말했듯이, 나는 당신의 제약 조건을 알지 못하지만 여기 RegEx를 사용하는 것은 아마 불필요한 복잡성을 추가하는 것이라고 생각합니다. –
Onorio의 요점에 덧붙여, regex 기반 접근법은 문자가 코드 주석을 나타내지 않을 때'//'문자를 포함하는 모든 코드를 깨뜨릴 것입니다. 예를 들어, URL과 같은 리터럴 문자열 내부. –
@JoelMueller, 또는 그의 코드도 여기에 있습니다.) – Benjol