역사적 관점
Wikipedia 기사 는 정규 표현식의 기원에 대해 매우 상세합니다 (Kleene, 1956). 원래 구문은 비교적 간단했다 *
, +
, ?
, |
및 그룹화 (...)
. 그것은 (간결했다 및 형식 언어가 간결 수학 표기법으로 표현하는 경향이 있기 때문에, 두 사람은 반드시 반대하지 않습니다, 읽기).
나중에, 구문과 기능은 편집자들과 함께 발전하고 Perl 과 함께 자랐습니다. Perl 은 디자인에 의해 간결 해 지려고했습니다 ( "공통 구성은 짧아야합니다" ). 이것은 구문을 많이 복잡하게 만들었지 만, 사람들은 이제 정규 표현식에 익숙해 져 있고 (읽지 않을 경우) 잘 작성합니다. 때로는 쓰기 전용이라는 사실은 너무 길면 일반적으로 올바른 도구가 아니라는 것을 나타냅니다.
정규 표현식은 악용 될 때 읽을 수없는 경향이 있습니다.
문자열 기반 정규 표현식을 넘어
다른 구문에 대해 말하기, 이제 (이미 존재 하나 살펴 보자 CL-ppcre 에서, 커먼 리스프를 ). 긴 정규 표현식은 ppcre:parse-string
다음과 같이 구문 분석 할 수 있습니다 .
(let ((*print-case* :downcase)
(*print-right-margin* 50))
(pprint
(ppcre:parse-string "^(?:([A-Za-z]+):)?(\\/{0,3})(0-9.\\-A-Za-z]+)(?::(\\d+))?(?:\\/([^?#]*))?(?:\\?([^#]*))?(?:#(.*))?$")))
... 결과는 다음과 같습니다.
(:sequence :start-anchor
(:greedy-repetition 0 1
(:group
(:sequence
(:register
(:greedy-repetition 1 nil
(:char-class (:range #\A #\Z)
(:range #\a #\z))))
#\:)))
(:register (:greedy-repetition 0 3 #\/))
(:register
(:sequence "0-9" :everything "-A-Za-z"
(:greedy-repetition 1 nil #\])))
(:greedy-repetition 0 1
(:group
(:sequence #\:
(:register
(:greedy-repetition 1 nil :digit-class)))))
(:greedy-repetition 0 1
(:group
(:sequence #\/
(:register
(:greedy-repetition 0 nil
(:inverted-char-class #\? #\#))))))
(:greedy-repetition 0 1
(:group
(:sequence #\?
(:register
(:greedy-repetition 0 nil
(:inverted-char-class #\#))))))
(:greedy-repetition 0 1
(:group
(:sequence #\#
(:register
(:greedy-repetition 0 nil :everything)))))
:end-anchor)
이 구문은 더 장황하며 아래 주석을 보면 더 읽기 쉬운 것은 아닙니다. 따라서 구문이 덜 간결하기 때문에 상황이 자동으로 명확해질 것이라고 가정하지 마십시오 .
그러나 정규식에 문제가 발생하면이 형식으로 변환하면 코드를 해독하고 디버그하는 데 도움이 될 수 있습니다. 이는 단일 문자 오류를 발견하기 어려운 문자열 기반 형식에 비해 한 가지 장점입니다.
이 구문 의 주요 장점 은 문자열 기반 인코딩 대신 구조적 형식을 사용하여 정규식을 조작하는 것입니다. 이를 통해 프로그램의 다른 데이터 구조와 같은 표현식 을 작성 하고 작성할 수 있습니다. 위의 구문을 사용하면 일반적으로 작은 부분에서 표현식을 작성하려고하기 때문입니다 ( CodeGolf 답변 참조 ). 예를 들어, 1을 쓸 수 있습니다 .
`(:sequence
:start-anchor
,(protocol)
,(slashes)
,(domain)
,(top-level-domain) ... )
문자열 연결 및 도우미 함수로 래핑 된 보간을 사용하여 문자열 기반 정규식을 구성 할 수도 있습니다. 그러나 코드 를 복잡 하게 만드는 문자열 조작에는 제한 이 있습니다 ( $(...)
배시의 백틱과 달리 중첩 문제에 대해 생각하십시오 . 또한 이스케이프 문자는 두통을 유발할 수 있습니다).
또한 위의 형식은 형식을 허용 (:regex "string")
하므로 간결한 표기법을 나무와 혼합 할 수 있습니다. 이 모든 것이 IMHO가 가독성과 구성 성을 좋게 만듭니다. 이 주소 delnan에 의해 표현 된 세 가지 문제 간접적으로 (즉,하지 정규 표현식 자체의 언어).
결론적으로
대부분의 경우 간결한 표기법을 읽을 수 있습니다. 역 추적 등을 포함하는 확장 표기법을 다루는 데 어려움이 있지만, 그 사용이 거의 정당화되지 않습니다. 정규 표현식을 부적절하게 사용하면 읽을 수없는 표현식이 생길 수 있습니다.
정규식은 문자열로 인코딩 할 필요가 없습니다. 정규식을 작성하고 작성하는 데 도움이되는 라이브러리 나 도구가있는 경우 문자열 조작과 관련된 많은 잠재적 인 버그를 피할 수 있습니다.
대안 적으로, 공식 문법은 더 읽기 쉽고 하위 표현식의 이름을 지정하고 추상화하는 데 더 좋습니다. 터미널은 일반적으로 간단한 정규식으로 표현됩니다.
1. 정규식은 응용 프로그램에서 상수 인 경향이 있으므로 읽기시 식을 작성하는 것이 좋습니다. 참조 create-scanner
및 load-time-value
:
'(:sequence :start-anchor #.(protocol) #.(slashes) ... )