에세이가 쓰여진 문서를 가지고 있다고 가정하십시오. 이 에세이를 구문 분석하여 특정 단어 만 선택하려고합니다. 시원한.
정규식을 사용하면 파일을 한 줄씩 파싱하고 단어별로 일치하는 것을 찾는 것보다 빠릅니다. 그렇다면 어떻게 작동합니까? 각 단어를 보는 것보다 어떻게 빨리 갈 수 있습니까?
에세이가 쓰여진 문서를 가지고 있다고 가정하십시오. 이 에세이를 구문 분석하여 특정 단어 만 선택하려고합니다. 시원한.
정규식을 사용하면 파일을 한 줄씩 파싱하고 단어별로 일치하는 것을 찾는 것보다 빠릅니다. 그렇다면 어떻게 작동합니까? 각 단어를 보는 것보다 어떻게 빨리 갈 수 있습니까?
답변:
어떻게 작동합니까?
오토마타 이론을 살펴보세요
간단히 말해서, 각 정규 표현식은 동등한 유한 오토 마톤을 가지며 유한 오토 마톤으로 컴파일되고 최적화 될 수 있습니다. 관련된 알고리즘은 많은 컴파일러 서적에서 찾을 수 있습니다. 이 알고리즘은 awk 및 grep과 같은 유닉스 프로그램에서 사용됩니다.
그러나 대부분의 최신 프로그래밍 언어 (Perl, Python, Ruby, Java (및 JVM 기반 언어), C #)는이 방법을 사용하지 않습니다. 그들은 정규식을 트리 또는 정규식의 다양한 하위 청크를 나타내는 일련의 구성으로 컴파일하는 재귀 역 추적 접근법을 사용합니다. 대부분의 최신 "정규 표현식"구문은 정규 언어 그룹 외부에있는 역 참조를 제공하며 (이것은 유한 오토마타로 표현되지 않음) 재귀 역 추적 방식으로 간단하게 구현할 수 있습니다.
최적화는 일반적으로보다 효율적인 상태 머신을 생성합니다. 예를 들어 : aaaab | aaaac | aaaad를 고려하면 일반 프로그래머는 10 분 안에 간단하지만 덜 효율적인 검색 구현 (세 개의 문자열을 개별적으로 비교)을 얻을 수 있습니다. 그러나 aaaa [bcd]와 동일하다는 것을 인식하면 처음 네 개의 'a'를 검색하여 [b, c, d]에 대해 다섯 번째 문자를 테스트하면 더 나은 검색을 수행 할 수 있습니다. 최적화 과정은 수년 전에 필자의 컴파일러 작업 중 하나 였으므로 대부분의 현대 정규식 엔진에도 있다고 가정합니다.
반면, 상태 머신은 "사소한 구현"에 비해 더 많은 공간을 사용하기 때문에 문자열을 받아 들일 때 이점이 있습니다. SQL 문자열에서 인용을 이스케이프 제거하는 프로그램을 고려하십시오. 즉, 1) 작은 따옴표로 시작하고 끝납니다. 2) 작은 따옴표는 두 개의 연속적인 작은 따옴표로 이스케이프됩니다. 따라서 입력 [ 'a' '']는 출력 [a ']를 산출해야합니다. 상태 머신을 사용하면 연속적인 작은 따옴표는 두 가지 상태로 처리됩니다. 이 두 상태는 다음과 같이 각 입력 문자가 정확히 한 번만 처리되도록 입력 기록을 기억하는 목적으로 사용됩니다.
...
S1->'->S2
S1->*->S1, output *, * can be any other character
S2->'->S1, output '
S2->*->END, end the current string
따라서 제 생각에는 정규 표현식이 사소한 경우에는 느리지 만 일반적으로 사람이 최적화를 안정적으로 수행 할 수 없다는 사실을 고려할 때 수동으로 만들어진 검색 알고리즘보다 빠릅니다.
문자열 검색과 같은 사소한 경우에도 스마트 엔진은 상태 맵의 단일 경로를 인식하고 해당 부분을 간단한 문자열 비교로 줄이고 상태 관리를 피할 수 있습니다.
프레임 워크 / 라이브러리의 특정 엔진은 엔진이 프로그래머가 일반적으로 필요하지 않은 많은 다른 작업을 수행하기 때문에 느려질 수 있습니다. 예 : .NET의 Regex 클래스는 일치, 그룹 및 캡처를 포함하여 많은 개체를 만듭니다.
aaaab|aaaac|aaaad
vs. 를 언급했습니다 aaaa[bcd]
. 두 가지가 수학적으로 동등하고 동일한 DFA를 생성하므로 프로그래머가 이해하기 쉬운 방식으로 정규 표현식을 표현할 수있는 자유를 더 많이 부여 할 필요가 있습니다. ..
컴퓨터가 빠르기 때문에 정규 표현식이 빠르게 보입니다.
1980 년대에 1 MIPS가 빠른 컴퓨터였던 정규식은 느리고 추악하고 계산 집약적이기 때문에 걱정, 관심사 및 연구의 상당히 큰 영역이었습니다. 영리한 알고리즘 개발이 따르고 도움이되었지만 요즘 모든 실제적인 목적을 위해 금이 간 기계가 기적을 기록하는 기적을보고 있습니다.
왜 문서를 검색하는 것보다 빠르다고 생각합니까?
예를 들어 몇 가지 트릭이 있습니다. A로 시작하고 B로 끝나는 10 글자 단어를 검색하는 경우 A를 찾은 다음 문자 9 위치가 B가 아닌 경우 일부를 건너 뛸 수 있습니다. 참조 크 누스 - 모리스 - 프랫 알고리즘을
정규 표현식이 빠른 이유는 무엇입니까?
실제로는 그렇지 않습니다. 그렇게 많지 않습니다. 그것은 우리 대부분이 알아 차릴만큼 느리지 않다는 것입니다. 예전의 느린 시절로 돌아 가면 훨씬 더 눈에 띄었습니다.
또한 모든 작업에 적합한 도구 인 망치 도 아닙니다 .
대부분의 라이브러리는 많은 개발자들이 수년 동안 노력한 결과로 가능한 한 마지막 성능을 최대한 발휘하기 때문에 RegEx의 코드 작성 속도 가 훨씬 빠릅니다 . 한 개인이 자신의 검색 코드로 복제하기가 어렵습니다.
기본 전제는 잘못되었습니다.
정규식이 단순한 검색보다 항상 빠른 것은 아닙니다. 그것은 모두 상황에 달려 있습니다. 표현의 복잡성, 검색되는 문서의 길이 및 전체 요인에 따라 다릅니다.
정규식은 간단한 파서 (시간이 걸리는)로 컴파일됩니다. 따라서 문서가 작 으면이 추가 시간이 유리합니다. 또한 표현식이 단순하면 정규 표현식으로 인해 이점이 없습니다.
표현이 복잡하고 문서가 충분히 크면 몇 가지 이점을 얻을 수 있습니다. 이것이 정규 표현식을 더 빨리 고려할만큼 충분한 지 여부는 검색에 얼마나 많은 노력을 기울이고 있는지에 따라 크게 달라집니다 (정규 표현식에는 라이브러리가 사용자가 생각하지 않았을 수있는 최적화가있을 수 있음).
내가 말하려는 것은 일반화 된 담요 답변이 없다는 것입니다. 특정 표현식 (및 알려진 문서 크기)이있는 경우 간단한 검색보다 표현식이 빠른지 여부와 그 이유에 대한 예 / 아니오 답변을 도출 할 수 있습니다.
정규 표현식의 실제 장점은 일단 작성하는 방법을 이해하면 복잡한 검색을 간결하게 표현할 수 있다는 것입니다. 일반화 된 양식이므로 일반적인 경우에 유용한 방식으로 검색 할 수있는 도구를 작성할 수 있습니다. 일반적으로 최소한 간단한 검색만큼 빠릅니다 (최소 크기의 문서에서; 이보다 작은 문서에서는 속도가 느리더라도 여전히 빠르기 때문에 중요하지 않습니다).
일부 고급 언어 (아마도 자바 스크립트)에서는 저급 언어 (아마도 C)로 구현 된 정규식 라이브러리를 사용하는 것이 고급 언어로 파서 논리를 작성하는 것보다 빠를 것입니다.
그럴듯한-이것이 실제로 사실인지 전혀 모른다.