Jamie Zawinski 의 인기 인용문 이 있습니다 .
어떤 사람들은 문제에 직면했을 때 "정규 표현을 사용할 것입니다."라고 생각합니다. 이제 두 가지 문제가 있습니다.
이 인용문은 어떻게 이해되어야합니까?
Jamie Zawinski 의 인기 인용문 이 있습니다 .
어떤 사람들은 문제에 직면했을 때 "정규 표현을 사용할 것입니다."라고 생각합니다. 이제 두 가지 문제가 있습니다.
이 인용문은 어떻게 이해되어야합니까?
답변:
일부 프로그래밍 기술은 일반적으로 프로그래머 (가 잘 이해되지 않습니다 정규 표현식 , 부동 소수점 , 펄 , AWK , IOC의 ... 등 ).
이들은 올바른 문제를 해결하기위한 놀랍도록 강력한 도구가 될 수 있습니다. 정규 표현식은 특히 정규 언어를 일치시키는 데 매우 유용합니다. 그리고 문제의 요점이 있습니다 : 일반 언어를 묘사하는 방법을 아는 사람은 거의 없습니다 (재미있는 기호를 사용하는 컴퓨터 과학 이론 / 언어학의 일부입니다 -Chomsky 계층 에서 읽을 수 있습니다 ).
이러한 것들을 다룰 때, 잘못 사용하면 실제로 원래 문제를 해결했을 가능성이 없습니다. 정규 표현식을 사용하여 HTML (매우 흔하게 발생하는) 과 일치 하면 가장자리 가 빠질 수 있습니다. 그리고 지금, 당신은 여전히 해결하지 못한 원래 문제와 잘못된 솔루션을 사용하여 그 주위에 떠있는 또 다른 미묘한 버그가 있습니다.
이것은 정규 표현식을 사용해서는 안된다는 것이 아니라, 그들이 해결할 수있는 문제들을 이해하고 그것을 해결할 수없고 신중하게 사용할 수 있도록 노력해야한다는 것입니다.
소프트웨어 유지 관리의 핵심은 유지 관리 가능한 코드를 작성하는 것입니다. 정규식을 사용하면 그 목표에 맞설 수 있습니다. 정규 표현식으로 작업 할 때 특수 도메인 특정 언어로 미니 컴퓨터 (특히 비 결정적 유한 상태 자동 장치 )를 작성했습니다. 이 언어로 'Hello world'를 작성하는 것은 쉽지만 기본적인 신뢰를 얻지 만, 식별하고 수정하기 어려운 추가 버그를 작성하지 않기 위해 일반 언어를 이해함으로써 더 나아가 야합니다. 정규 표현식이있는 프로그램의 일부는 아닙니다).
이제 새로운 문제가 생겼습니다. 정규식 도구를 사용하여 문제를 해결할 때 (부적절한 경우), 두 가지 버그가 있습니다. 두 가지 버그가 있습니다. 두 가지 버그는 다른 추상화 계층에 숨겨져 있기 때문에 찾기가 더 어렵습니다.
정규 표현식, 특히 사소한 표현은 코딩, 이해 및 유지 관리가 어려울 수 있습니다. 질문자가 질문에 [regex]
대한 답변이 정규식이라고 가정하고 그 뒤에 붙어 있는 스택 오버플로 태그의 질문 수만 살펴보십시오 . 많은 경우에 문제는 다른 방식으로 해결 될 수 있습니다.
이것은 정규식을 사용하기로 결정하면 이제 두 가지 문제가 있음을 의미합니다.
기본적으로, 나는 당신이 문제를 해결할 다른 방법이 없다면 정규식 만 사용해야한다는 것을 의미한다고 생각합니다. 다른 솔루션은 코딩, 유지 관리 및 지원이 더 쉬울 것입니다. 속도가 느리거나 효율이 떨어질 수 있지만 유지 관리가 쉬워지지 않으면 지원 및 지원이 가장 중요합니다.
그것은 진실의 곡물에도 불구하고 주로 뺨에 뺨 농담입니다.
정규식이 잘 맞는 몇 가지 작업이 있습니다. 한 번은 500 줄의 수동으로 작성된 재귀 강하 파서 코드를 하나의 정규 표현식으로 바꾸어 완전히 디버그하는 데 약 10 분이 걸렸습니다. 사람들은 정규 표현식을 이해하고 디버깅하기가 어렵지만 적절하게 적용되는 규칙은 손으로 설계된 거대한 파서만큼 디버그하기가 쉽지 않다고 말합니다. 내 예에서는 정규식이 아닌 솔루션의 모든 주요 사례를 디버깅하는 데 2 주가 걸렸습니다.
그러나 벤 아저씨를 다음과 같이 표현하면 :
표현력이 뛰어나면 큰 책임이 따릅니다.
다시 말해, 정규 표현식은 언어에 표현력을 더해 주지만, 주어진 작업에 대해 가장 읽기 쉬운 표현 모드를 선택하도록 프로그래머에게 더 많은 책임을 부여합니다.
어떤 것은 처음에는 정규 표현식에 좋은 작업처럼 보이지만 그렇지 않습니다. 예를 들어 HTML과 같이 중첩 된 토큰이있는 모든 것이 있습니다. 때로는 더 간단한 방법이 더 명확 할 때 사람들이 정규식을 사용합니다. 예를 들어, string.endsWith("ing")
동등한 정규 표현식보다 이해하기 쉽습니다. 때때로 사람들은 큰 문제를 하나의 정규 표현식으로 만들려고하는데, 조각으로 나누는 것이 더 적절합니다. 때로는 사람들이 적절한 추상화를 작성하지 못하고 동일한 작업을 수행하는 잘 알려진 함수를 작성하는 대신 정규식을 반복해서 반복합니다 (아마도 정규식으로 내부 구현).
어떤 이유로 든 정규 표현식은 단일 책임 및 DRY와 같은 일반적인 소프트웨어 엔지니어링 원칙에 대한 사각 지대를 만드는 이상한 경향이 있습니다. 그렇기 때문에 자신을 사랑하는 사람들조차도 때때로 문제를 발견하는 것입니다.
Jeff Atwood는이 글을 인용 한 블로그 게시물에서 다른 해석을 제공합니다. 정규식 : 이제 두 가지 문제가 있습니다 ( 링크에 대한 행복감 )
1997 년 실의 Jamie 게시물의 전체 내용을 분석하면 다음과 같은 결과를 얻을 수 있습니다.
Perl의 본질은 다른 모든 기술을 거의 배제하기 위해 정규 표현식을 사용하도록 권장합니다. 그들은 A 지점에서 B 지점으로 갈 수있는 가장 "명백한"(적어도 더 잘 모르는 사람들에게) 멀고 멀리 떨어져 있습니다.
첫 번째 인용문은 너무 어리석어 서 심각하게 받아 들일 수 없습니다. 그러나 이것은 전적으로 동의합니다. 제이미가하려고하는 요점은 다음과 같습니다. 정규 표현식 자체가 악한 것이 아니라 정규 표현식을 과도하게 사용하는 것은 악한 것입니다.
당신이 경우에도 않는 완전히 정규 표현식을 이해, 당신은으로 실행 황금 망치 가 쉽고 (참조 일반 코드와 같은 일을하는 것이 더 명확했을 때 정규 표현식에 문제를 해결하기 위해 노력하고, 문제 CodingHorror : 정규식 사용 대 정규식 학대 ).
인용문의 맥락을 살펴보고 Atwood보다 자세한 내용을 다루는 또 다른 블로그 게시물이 있습니다. Jeffrey Friedl의 블로그 : 유명한 "지금 두 가지 문제가 있습니다"인용문의 출처
이 인용문에는 몇 가지 일이 있습니다.
이 인용문 은 이전 농담을 다시 언급 한 것입니다.
문제가 생길 때마다 "AWK를 사용하자"고 말하는 사람들이 있습니다. 이제 두 가지 문제가 있습니다. — 디 틸 브룩
그것은 농담과 실제 발굴이지만 정규식을 다른 나쁜 솔루션과 연결하여 나쁜 솔루션으로 강조하는 방법이기도합니다. 그것은 중대 하, 하, 심각한 순간.
이 인용문은 의도적으로 해석에 개방되어 있습니다. 그 의미는 간단합니다. 정규 표현식을 사용한다는 아이디어 만 발표해도 문제가 해결되지 않았습니다. 또한 사용하는 언어와 다른 규칙을 가진 언어를 추가하여 코드의인지 복잡성을 증가 시켰습니다.
농담으로 재미 있기는하지만 정규식이 아닌 솔루션의 복잡성과 정규식 솔루션의 복잡성과 정규식 포함의 추가 복잡성을 비교해야합니다. 정규식을 추가하는 데 드는 추가 비용에도 불구하고 정규식 문제를 해결하는 것이 좋습니다.
정규 표현식은 현재 설정되어 있지 않거나 형식화되지 않은 다른 모든 내용을 유지하고 있습니다.이 문서에서는 읽기 어려운 경우가 있지만, 불행히도 형식화를 허용하지 않으며 사람들이 당신이 할 수 있다는 사실을 모르기 때문에 불행히도 그 결과물을 읽을 수 없습니다.
(정규 표현식은 다른 형식화되지 않은 콘텐츠보다 읽거나 유지하기가 더 나쁘지 않습니다. 실제로 정규 표현식 이이 텍스트보다 읽기 쉽습니다. 그러나 불행히도 일부 구현에서는 형식 지정 및 일반 사용자를 허용하지 않기 때문에 평판이 좋지 않습니다. 할 수 있다는 것을 몰라요.)
다음은 간단한 예입니다.
^(?:[^,]*+,){21}[^,]*+$
어쨌든 읽거나 유지하기가 어렵지는 않지만 다음과 같이하면 더 쉽습니다.
(?x) # enables comments, so this whole block can be used in a regex.
^ # start of string
(?: # start non-capturing group
[^,]*+ # as many non-commas as possible, but none required
, # a comma
) # end non-capturing group
{21} # 21 of previous entity (i.e. the group)
[^,]*+ # as many non-commas as possible, but none required
$ # end of string
그것은 약간의 오버 윗 예제 (설명은 논평 $
과 유사합니다 i++
)이지만 분명히 읽고 이해하고 유지하는 데 아무런 문제가 없어야합니다.
정규 표현식이 적합한시기와 나쁜 생각 일 때 분명한 한, 아무 문제가 없으며 대부분 JWZ 견적이 실제로 적용되지 않습니다.
*+
? 그것은 (기능적으로) 다른 것과 어떻게 다른 *
가요?
*+
이 경우 말 그대로 의미가 없습니다 . 모든 것은 고정되어 있으며 최대 22 개까지 셀 수있는 자동 장치로 단일 패스로 일치시킬 수 있습니다. 쉼표가 아닌 세트의 올바른 수정자는 평범 *
합니다. (또한 여기에서 욕심쟁이와 욕심없는 매칭 알고리즘 사이에는 차이가 없어야합니다. 매우 간단한 경우입니다.)
ChrisF의 답변 외에도 정규 표현식은 "코딩, 이해 및 유지 관리가 어렵다"는 단점이 있습니다. HTML과 같이 할 수없는 것을 구문 분석하기 위해 사람들을 속이려고 할 정도로 강력합니다. "HTML 구문 분석 방법"에 대한 SO에 대한 수많은 질문을 참조하십시오. 예를 들어, 가장 서사시 대답 SO의 모두!
정규식은 매우 강력하지만 작고 큰 문제가 있습니다. 그들은 쓰기가 어렵고 읽기가 거의 불가능합니다.
가장 좋은 경우 정규식을 사용하면 문제가 해결되므로 복잡한 코드의 유지 관리 문제 만 발생합니다. 정규 표현식을 제대로 얻지 못하면 원래 문제와 읽을 수없는 코드 문제가 있습니다.
때로는 정규식을 쓰기 전용 코드라고합니다. 수정이 필요한 정규 표현식에 직면하면 표현식을 이해하려고 시도하는 것보다 처음부터 시작하는 것이 더 빠릅니다.
문제는 정규식이 복잡한 짐승이며 정규식을 완벽하게 사용하는 경우에만 문제를 해결한다는 것입니다. 그렇지 않으면 원래 문제 와 정규식이라는 두 가지 문제가 발생합니다 .
당신은 그것이 100 줄의 코드 작업을 할 수 있다고 주장하지만 100 줄의 명확하고 간결한 코드가 한 줄의 정규 표현식보다 낫다는 주장을 할 수도 있습니다.
이에 대한 증거가 필요한 경우 :이 SO Classic을 확인 하거나 SO 정규식 태그를 통해 간단하게 빗질 할 수 있습니다.
2014 년에 요청하면 오늘날의 상황과 비교하여 1997 년의 상황에서 프로그래밍 언어 이데올로기에 초점을 맞추는 것이 흥미로울 것입니다. 여기서는이 토론에 참여하지 않겠지 만 Perl과 Perl 자체에 대한 의견은 크게 바뀌 었습니다.
그러나 2013 년 상황 ( de l' eau a coulé sous les ponts depuis)을 유지하려면 Jamie Zawinski의 직접 인용 인 유명한 XKCD 만화를 사용하여 따옴표로 재현하는 데 중점을 두는 것이 좋습니다 .
먼저 나는 그것이 Zawinski 인용에 대한 참조했기 때문에이 만화를 이해하는 문제가 있었다 와 제이 - Z의 노래 가사의 견적, 그리고 GNU의의 참조 program --help -z
플래그 2를 내가 그것을 이해하는 것이 너무 많은 문화를했다, 그래서.
나는 그것이 재미 있다는 것을 알고, 느끼고 있었지만, 왜 그런지 몰랐습니다. 사람들은 종종 Perl과 정규 표현식에 대해 농담을합니다. 특히 가장 프로그래밍 언어가 아니기 때문에 왜 재미 있어야하는지 모르겠습니다. 아마도 Perl 상인들이 바보 같은 일을 하기 때문일 것 입니다.
따라서 초기 인용문은 실제 도구 (고통?)를 기반으로 한 비꼬는 농담 인 것처럼 보입니다. 해머가 메이슨을 해칠 수있는 것처럼, 개발자가 그가 다칠 수있는 도구 (뇌, 감정)가 아닌 도구로 프로그래밍하는 것은 메이슨을 해칠 수 있습니다. 때로는 큰 논쟁은 대한 도구가 발생 최선이지만의 문제의 원인은 거의 쓸모의 취향 이나 프로그래밍 팀의 맛 , 문화 또는 경제적 인 이유. 이것에 대한 또 다른 훌륭한 XKCD 만화 :
나는 사람들이 정규 표현식에 대해 고통을 느끼는 것을 이해할 수 있으며 다른 도구가 정규 표현식 용으로 더 적합하다고 생각합니다. @ karl-bielefeldt가 귀하의 질문 에 큰 표현력으로 대답함에 따라 큰 책임이 따르고 정규 표현식 이 특히 염려됩니다. 개발자가 정규 표현식을 처리하는 방법을 신경 쓰지 않으면 나중에 코드를 유지 관리하는 사람들에게 고통을 줄 것입니다.
나는 Damian Conw ay의 Perl Best Practices (2005 년 책) 의 전형적인 예를 보여주는 인용구로 인용 된 재연에 대한이 답변으로 마무리 할 것 입니다.
그는 다음 과 같은 패턴 을 작성 한다고 설명합니다 .
m{'[^\\']*(?:\\.[^\\']*)*'}
... 다음 과 같은 프로그램을 작성하는 것보다 더 이상 용납되지 않습니다 .
sub'x{local$_=pop;sub'_{$_>=$_[0
]?$_[1]:$"}_(1,'*')._(5,'-')._(4
,'*').$/._(6,'|').($_>9?'X':$_>8
?'/':$")._(8,'|').$/._(2,'*')._(
7,'-')._(3,'*').$/}print$/x($=).
x(10)x(++$x/10).x($x%10)while<>;
그러나이 수 다시 작성 그것의, 여전히 꽤 아니지만, 적어도 지금은 생존입니다.
# Match a single-quoted string efficiently...
m{ ' # an opening single quote
[^\\']* # any non-special chars (i.e., not backslash or single quote)
(?: # then all of...`
\\ . # any explicitly backslashed char
[^\\']* # followed by any non-special chars
)* # ...repeated zero or more times
' # a closing single quote
}x
이러한 종류의 직사각형 코드 는 명확하고 유지 보수 가능하며 읽을 수있는 형식으로 형식화 할 수있는 정규식이 아닌 두 번째 문제입니다.
/* Multiply the first 10 values in an array by 2. */ for (int i = 0 /* the loop counter */; i < 10 /* continue while it is less than 10 */; ++i /* and increment it by 1 in each iteration */) { array[i] *= 2; /* double the i-th element in the array */ }
컴퓨터 과학에서 배워야 할 것이 있다면 Chomsky 계층 구조 입니다. 정규 표현식의 모든 문제는 문맥이없는 문법을 구문 분석하려는 시도에서 비롯된 것입니다. CFG에서 중첩 수준에 제한을 적용하거나 제한을 적용 할 수 있다고 생각하면 길고 복잡한 정규 표현식을 얻을 수 있습니다.
정규식은 전체 구문 분석보다 토큰 화에 더 적합합니다.
그러나 프로그래머가 구문 분석해야 할 놀랍게도 많은 것들이 일반 언어로 구문 분석 가능합니다 (또는 일반 언어로 거의 구문 분석 가능하며 조금 더 코드를 작성하는 경우 ...).
따라서 "aha, 텍스트를 따로 골라야합니다. 정규 표현식을 사용하겠습니다"라는 습관이 있다면 푸시 다운 오토 마톤, CFG 파서 또는 훨씬 더 강력한 문법. 그것은 보통 눈물로 끝납니다.
그래서 나는 인용문이 너무 많은 정규 표현식을 슬프게 생각하지는 않지만 그것들의 사용 (그리고 잘 사용되면 실제로 매우 유용합니다)이지만 정규 표현식에 대한 과도한 의존 (또는 특히 비판적 선택) .
jwz는 그 인용구로 로커를 벗어났습니다. 정규 표현식은 다른 언어 기능과 다르지 않습니다. 쉽게 조일 수 있고, 우아하게 사용하기 어렵고, 강력하고, 때로는 부적절하며, 자주 문서화되고, 종종 유용합니다.
부동 소수점 산술, 클로저, 객체 지향, 비동기 I / O 또는 기타 이름을 지정할 수 있습니다. 당신이 무엇을하고 있는지 모른다면, 프로그래밍 언어는 당신을 슬프게 할 수 있습니다.
정규식을 읽기 어렵다고 생각되면 해당 패턴을 사용하기위한 동등한 구문 분석기 구현을 읽으십시오. 정규 표현식은 전체 파서보다 작기 때문에 종종 승리합니다. 대부분의 언어에서는 속도도 빠릅니다.
자체 홍보 블로거는 자격이없는 진술을하기 때문에 정규 표현식 (또는 다른 언어 기능)을 사용하지 마십시오. 직접 시도해보고 어떤 것이 효과가 있는지보십시오.
이에 대한 내가 가장 좋아하는 심층 답변은 유명한 Rob Pike가 내부 Google 코드 주석에서 재현 한 블로그 게시물에서 제공합니다 . and.html
요약은 그것이 나쁘지 는 않지만, 특히 일부 입력을 분석하고 구문 분석 할 때 반드시 적합하지 않은 작업에 자주 사용된다는 것입니다.
정규식은 쓰기가 어렵고 쓰기가 어렵고 다른 기술에 비해 비쌀 수 있습니다. 반면 Lexers는 정확하게 작성하기가 쉽고 (간결하지는 않지만) 테스트하기가 매우 쉽습니다. 영숫자 식별자를 찾아보십시오. 정규 표현식 ( "[a-ZA-Z _] [a-ZA-Z_0-9] *"와 같은 것)을 작성하는 것은 그리 어렵지 않지만 간단한 루프로 작성하는 것은 그리 어렵지 않습니다. 그러나 루프의 성능은 훨씬 높을 것이며 커버 아래의 코드는 훨씬 적습니다. 정규식 라이브러리는 큰 것입니다. 식별자를 파싱하기 위해 하나를 사용하는 것은 우유를 위해 가게에 가기 위해 페라리를 사용하는 것과 같습니다.
그는 정규 표현식이 텍스트 편집기에서 패턴의 일회용 일치에 유용하지만 컴파일 된 코드에는 거의 사용되지 않는 등의 식으로 유용하다고 주장합니다. 읽을 가치가 있습니다.
정규식은 빠르고 더러운 텍스트 구문 분석에 널리 사용됩니다. 그것들은 단순한 문자열 매치보다 조금 더 복잡한 패턴을 표현하는 훌륭한 도구입니다.
그러나 정규 표현식이 더 복잡한 서버 문제를 겪으면서 고개를 들었습니다.
따라서 텍스트 처리 문제로 시작하고 정규 표현식을 적용하고 해결하려는 원래 문제를 해결하려는 원래 문제 (그러나 올바르게 해결하지는 않음)라는 두 가지 문제로 끝납니다. 원래 문제.