정규식을 사용하지 않아야 할 때? [닫은]


50

정규 표현식은 프로그래머의 무기고에서 강력한 도구이지만, 최선의 선택이 아니거나 심지어 완전히 해로운 경우도 있습니다.

간단한 예제 # 1은 많은 버그로 알려진 regexp를 사용 하여 HTML을 구문 분석 하는 것입니다. 아마도 이것은 일반적 으로 구문 분석 에 기인합니다 .

그러나 정규 표현식에 대한 명확한 영역이 있습니까?


추신 : " 당신이 묻는 질문은 주관적이고 폐쇄 될 가능성이 높습니다. "-나는 정규 표현식 사용이 문제를 일으키는 것으로 알려진 예에 관심이 있음을 강조하고 싶습니다.


9
정규 표현식으로 HTML을 파싱하는 것은 "많은 버그로 알려진 길"이 아닙니다. 실제로 불가능하다 .
Kramii Reinstate Monica

19
그것은 불가능할뿐만 아니라 광기와 영원한 저주로
Martin Wickman

3
@ Jörg : Regexp는 정규 표현식의 약어 일뿐입니다.
Joren

3
@ Jörg : 수학에서의 정규 표현식과 소프트웨어 라이브러리에서의 구현 사이에 큰 차이가 있다는 것은 매우 사실입니다. 또한 대부분의 정규 표현식 라이브러리에는 정규 언어 만 허용하는 것 이상의 확장 기능이 있으며 정규 표현식을 호출하는 것이 항상 그렇게 적합한 것은 아닙니다. 나는 두 가지 다른 개념이 있다는 것에 동의합니다. 그러나 그들은 같은 이름을 가지고 있습니다. 정규 표현식은 여전히 ​​약어 일뿐 용어 자체는 아닙니다. 이 사이트에서 소프트웨어 라이브러리에 대한 전체 용어를 사용하는이 예제가 많이 있습니다.
Joren

2
@ Jörg-이것들은 의미 론적입니다. 이러한 패턴을 다른 이름으로 부르는 것이 좋습니다 ( "정규 표현식은 일반 언어에 대한 것"오류를 피하기 위해), "정규 표현식"/ "정규 표현식"은 아주 좋은 시도가 아니며 추가 혼란.
Kobi

답변:


60

정규식을 사용하지 마십시오 :

  • 파서가있을 때.

이것은 HTML로 제한되지 않습니다 . 스키마를 알고 있고 절대 변경되지 않는다는 것을 알고 있어도 간단한 유효한 XML을 정규식으로 구문 분석 할 수 없습니다.

예를 들어 C # 소스 코드를 구문 분석 하지 마십시오 . 의미있는 트리 구조 또는 토큰을 얻으려면 대신 구문 분석하십시오.

  • 보다 일반적으로 업무 수행을위한 더 나은 도구가있을 때.

작은 대문자와 대문자를 모두 검색해야한다면 어떻게합니까? 정규식을 좋아한다면 그것들을 사용할 것입니다. 그러나 두 개의 검색을 하나씩 사용하는 것이 더 쉽고 빠르거나 읽을 수 있습니까? 대부분의 언어에서 더 나은 성능을 달성하고 코드를 더 읽기 쉽게 만들 수 있습니다.

예를 들어, Ingo의 답변에있는 샘플 코드는 정규식을 사용해서는 안되는 좋은 예입니다. 을 검색 foo한 다음을 검색하십시오 bar.

  • 인간의 글을 파싱 할 때.

좋은 예는 외설 필터입니다. 일반적으로 구현 하는 것은 나쁜 생각 일뿐 만 아니라 정규 표현식을 사용하여 유혹을 받으면 잘못 할 수 있습니다. 인간이 단어, 숫자, 문장을 쓸 수있는 방법은 많이 있지만 다른 사람은 이해할 수 있지만 규칙적인 표현은 아닙니다. 따라서 실제 외설을 사로 잡는 대신 정규 표현으로 인해 다른 사용자를 해칠 수 있습니다.

  • 일부 유형의 데이터를 확인할 때.

예를 들어 정규식을 통해 전자 메일 주소의 유효성을 검사하지 마십시오. 대부분의 경우 잘못 할 것입니다. 드문 경우지만 올바르게 수행 하고 6 343 자 길이의 코딩 공포로 마무리 합니다.

올바른 도구가 없으면 실수를 저지를 것입니다. 그리고 당신은 마지막 순간에 그들을 알 수 있습니다. 깨끗한 코드에 신경 쓰지 않으면 주석이없고 공백이없고 줄 바꿈이없는 20 줄 문자열을 작성합니다.

  • 코드를 읽을 때 그런 다음 다른 개발자가 매번 또 다시 읽고 또 읽습니다.

진심으로, 코드를 가져 와서 검토하거나 수정해야한다면 20 줄 길이의 문자열로 많은 기호를 이해하려고 일주일을 보내고 싶지 않습니다.


9
"코드를 가져 와서 검토하거나 수정해야한다면 20 줄 길이의 문자열을 이해하기 위해 일주일을 보내고 싶지는 않습니다." +1!
funkybro

1
이것은 스택 오버플로에서 누나보다 훨씬 더 나은 대답입니다. stackoverflow.com/questions/7553722/…
Kobi

1
Perl / PCRE (그리고 아마도 다른 현대 정규식 풍미도)를 사용하는 경우, 서브 루틴, 캡처 그룹 및 (?(DEFINE))어설 션 에 대해 읽어보십시오.) 정규 표현식을 사용하여 매우 깨끗한 정규 표현식 을 작성할 수 있습니다. yacc 또는 이와 비슷하게 작성하는 것과 매우 유사합니다.)
NikiC

2
블랙리스트에 포함 된 단어를 구문 분석하기 위해 정규식을 사용하는 것은 명백한 오류입니다.
Dan Ray

세계에서와 같은 문자열에 정규식을 던지는 것을 피할 이유가 없습니다 "<a href='foo'>stuff</a>". 현대식 정규 표현식에는 아무런 문제가 없습니다.
tchrist

18

가장 중요한 것은 구문 분석하는 언어가 일반 언어 가 아닌 경우 입니다 .

HTML은 하지 정규 언어와 정규 표현식으로 파싱 것은 없습니다 (어렵거나 버그 코드에 대한 도로뿐만 아니라) 가능합니다.


4
잘못된! 최신 정규 표현식 (Perl, PCRE, Java, .NET 등)을 사용하는 경우 재귀 및 어설 션을 수행 할 수 있으므로 컨텍스트가없고 컨텍스트에 맞는 문법도 구문 분석 할 수 있습니다.
NikiC

9
@ 니키 틀리 진 않아. "현대 정규식 맛"은 정규 표현식이 아닙니다 (정규 언어를 구문 분석하는 데 사용할 수 있으므로 이름). 나는 PRE로 더 많은 것을 할 수 있지만 그것들을 단지 "정규 표현"이라고 부르지 않을 것에 동의한다 (원래 질문에서와 같이).
Matteo

1
현대식 정규식은 할머니가 가르쳐 준 것 이상으로 정규식이 할 수있는 것이 그녀의 조언이 중요하지 않습니다. 심지어 원시 정규 표현식조차도 대부분의 HTML 스 니펫을 처리 할 수 ​​있습니다. 이 담요 금지는 어리 석고 비현실적입니다. 이런 종류의 일을 위해 정규식이 만들어졌습니다 . 그리고 네, 내가 무슨 말을하는지 알고 있습니다.
tchrist

12

하나는 종종 본다 유래에 사람들은 주어진 문자열 않습니다하는지 여부를 확인 정규 표현식에 요청 하지 이런 저런 포함되어 있습니다. 이것은 IMHO의 정규 표현의 목적을 반대로하는 것입니다. 솔루션이 존재하더라도 (부정적인 비하인드 어설 션 또는 그러한 것들을 사용) 정규식을 사용하여 프로그램 논리로 부정적인 경우를 처리하고 처리하는 것이 훨씬 낫습니다.

예:

# bad
if (/complicated regex that assures the string does NOT conatin foo|bar/) {
    # do something
}

# appropriate
if (/foo|bar/) {
    # error handling
} else {
    # do something
}

1
+1 : 몇 번, 나는 정규식으로 코너에 코드를 작성하는 것을 피하고 "좋아요, 내가 구체적으로 맞추려고하는 것은 무엇입니까?" "무엇을 피하려고합니까?"

5

두 가지 경우 :

더 쉬운 방법이있을 때

  • 대부분의 언어는 한 문자열이 다른 문자열의 하위 집합인지 확인하기 위해 INSTR과 같은 간단한 기능을 제공합니다. 그것이 당신이하고 싶은 일이라면 더 간단한 기능을 사용하십시오. 자신 만의 정규식을 쓰지 마십시오.

  • 복잡한 문자열 조작을 수행하는 데 사용할 수있는 라이브러리가있는 경우 고유 한 정규식을 작성하는 대신 라이브러리를 사용하십시오.

정규식이 충분히 강력하지 않은 경우

  • 파서가 필요한 경우 파서를 사용하십시오.

0

정규 표현식은 재귀 구조를 식별 할 수 없습니다 . 이것이 근본적인 한계입니다.

JSON을 가져 오십시오-매우 간단한 형식이지만 객체에 다른 객체를 멤버 값 (임의로 깊이 포함)으로 포함 할 수 있으므로 구문은 재귀 적이며 정규 표현식으로 구문 분석 할 수 없습니다. 반면에 CSV 재귀 구조를 포함하지 않기 때문에 정규 표현식으로 구문 분석 할 수 있습니다.

간단히 말해서 정규 표현식은 패턴 자체를 참조 할 수 없습니다. 당신은 말할 수 없습니다 :이 시점에서 구문의 전체 패턴을 다시 일치시킵니다. 다시 말해서, 정규 표현식은 선형으로 만 일치하며 중첩 패턴의 깊이를 추적 할 수있는 스택을 포함하지 않습니다.

형식이 얼마나 복잡하거나 복잡한 지와는 아무런 관련이 없습니다. S- 표현은 정말 간단하지만 정규식으로 구문 분석 할 수 없습니다. 반면에 CSS2는 매우 복잡한 언어이지만 재귀 구조를 포함하지 않으므로 정규식으로 구문 분석 할 수 있습니다. (재귀 구문이있는 CSS 표현식으로 인해 CSS3에는 적용되지 않습니다.)

따라서 정규식 만 사용하여 HTML을 구문 분석하는 것이 추악하거나 복잡하거나 오류가 발생하기 쉽기 때문이 아닙니다. 그것은 단순히 불가능하다는 것 입니다.

재귀 구조를 포함하는 형식을 구문 분석해야하는 경우 재귀 구조 수준을 추적하려면 스택으로 정규식 사용을 보충해야합니다. 이것은 일반적으로 파서의 작동 방식입니다. 정규식은 "선형"부분을 인식하는 데 사용되고 정규 표현식 외부의 사용자 정의 코드는 중첩 구조를 추적하는 데 사용됩니다.

일반적으로 이와 같은 구문 분석은 별도의 단계로 나뉩니다. 토큰 화는 정규식을 사용하여 입력을 단어, 문장 부호, 대괄호 등과 같은 "토큰"시퀀스로 나누는 첫 번째 단계입니다. 구문 분석은 이러한 토큰이 계층 구조 인 구문 트리로 구문 분석되는 다음 단계입니다.

따라서 정규식으로 HTML 또는 C #을 구문 분석 할 수 없다고 들리면 정규식은 여전히 ​​구문 분석기의 중요한 부분입니다. 정규식 사용 하고 도우미 코드는 사용하지 않고 그러한 언어를 구문 분석 할 수 없습니다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.