왜 정규 표현이 그렇게 논란이 되는가? [닫은]


212

정규식 (RegEx-es라고도 함)을 탐색 할 때 정규식을 성배라고 생각하는 사람들이 많이 있습니다. 너무 복잡해 보이는 것은 질문에 대한 답이어야합니다. 그들은 정규 표현식을 사용하여 모든 문제를 해결할 수 있다고 생각하는 경향이 있습니다.

반면에 정규 표현식을 피하려고하는 사람들도 많습니다. 정규 표현식이 더 컴팩트 한 솔루션 일지라도 정규 표현식을 둘러싼 방법을 찾고 추가 코딩을 받아들입니다.

왜 정규 표현이 논란의 여지가 있는가? 작동 방식에 대한 오해가 널리 퍼져 있습니까? 아니면 정규 표현이 일반적으로 느리다는 것이 넓은 믿음 일 수 있습니까?


9
이것이 토론이라면, 닫혀서는 안됩니까? 하지만 거기에 실제 질문이 있으므로 토론 태그가 속하지 않을 수 있습니까?
RCIX 2016 년

6
농담이 없습니다. 당신은 그것을 가져오고 사람들은 여기에서 모든 미치게 시작합니다.
Ryan Florence

1
질문에서 좋은 관찰과 표현!
imz-Ivan Zakharyaschev


문제는 여기에 규칙을 적용해야하는 의견에 근거한 의견입니다 (또는 정확한 답변을 목표로 질문을 편집해야 함). 그것은 정규식 논란이 튜토리얼과 매뉴얼의 부정확성에서 나온 것이라고 가정합니다. 모든 시간 정보가 혼합되어 있지 않은 경우 대부분의 시간 동안 추가로 모든 특성이 제공되지는 않습니다. 해당 언어를 잘못 사용하면 다른 의미를 가질 수 있다는 것을 알게 될 것입니다. 마지막으로 특수 정규식 문자는 혼동을 더하는 하나의 의미로 제한되지 않습니다.
intika

답변:


136

나는 사람들이 느리기 때문에 정규 표현식에 반대한다고 생각하지 않고 오히려 읽고 쓰기가 어렵고 올바르게 이해하기가 까다로워서 생각합니다. 정규식이 문제에 대해 효과적이고 간결한 솔루션을 제공하는 상황이 있지만 때로는 읽기 쉽고 유지 관리가 쉬운 코드 섹션을 사용하는 것이 더 나은 상황에 처하게됩니다.


2
그리고 네, 정규 표현식은 간단한 기능을 사용하는 것에 비해 매우 느릴 수 있습니다. 임의의 (사용자 제공) 입력에 직면 할 때 느릴뿐만 아니라 정규식 엔진의 성능을 완전히 예측할 수 없습니다 .
Pacerier

1
정규식이 어떻게 작동하는지 안다면 전혀 문제가되지 않습니다.
Shiplu Mokaddim은

8
@pacerier, 그것은 느린 패턴 이 아니며 , 느린 엔진 입니다. 대부분의 (현대적인) 정규식 엔진 은 스택 머신과 역 추적을 사용하기 때문에 복잡한 패턴 (예 : many |또는 .*)에 적합하지 않습니다 . 따라서 Perl, Java, Python, Ruby에서 정규 표현식을주의해서 조정해야 grep합니다. 예를 들어 구식 정규 표현식 엔진은 먼저 패턴을 DFA로 컴파일합니다. 그 후, 패턴의 복잡성은 크게 관련이 없습니다. 방금 동일한 텍스트와 패턴에 Java와 grep을 사용했습니다. 22 분 대 2 초. 과학은 다음과 같습니다. swtch.com/~rsc/regexp/regexp1.html
hagello

122

정규식을 유지 보수 가능하게 만들기

이전에 "정규 표현식"으로 언급 된 패턴을 이해하기위한 주요한 발전 은 공백 (줄 바꿈, 들여 쓰기) 및 주석을 허용하는 Perl의 /x정규 표현식 플래그 (때때로 (?x)포함 된 경우)입니다. 이렇게하면 가독성이 향상되어 유지 관리 성이 향상됩니다. 공백은인지 청크를 허용하므로 어떤 그룹으로 무엇을 볼 수 있습니다.

현대식 패턴은 이제 상대적으로 번호가 매겨진 이름과 역 참조를 모두 지원합니다. 그 말 더 이상 필요는 당신이 필요로하는 것을 파악하는 캡처 그룹을 계산하는 $4\7. 추가 패턴에 포함될 수있는 패턴을 만들 때 도움이됩니다.

다음은 상대적으로 번호가 매겨진 캡처 그룹의 예입니다.

$ dupword = qr {\ b (? : (\ w +) (? : \ s + \ g {-1}) +) \ b} xi;
$ quoted = qr {([ " ']) $ dupword \ 1} x;

다음은 명명 된 캡처의 뛰어난 접근 방식의 예입니다.

$dupword = qr{ \b (?: (?<word> \w+ ) (?: \s+ \k<word> )+ ) \b }xi;
$quoted  = qr{ (?<quote> ["'] ) $dupword  \g{quote} }x;

문법 정규식

무엇보다도 이러한 명명 된 캡처를 (?(DEFINE)...)블록 내에 배치 하여 패턴의 개별 명명 된 요소 실행과 선언을 분리 할 수 ​​있습니다. 이는 패턴 내에서 서브 루틴처럼 작동하도록합니다.
"문법 정규식"이런 종류의 좋은 예는에서 찾을 수있다 이 대답 하고 이것 . 이것들은 문법 선언과 훨씬 비슷합니다.

후자가 상기 시키 듯이 :

… 라인 노이즈 패턴을 쓰지 마십시오. 당신은 할 필요가 없습니다. 공백, 주석, 서브 루틴 또는 영숫자 식별자를 금지하는 프로그래밍 언어를 유지할 수 없습니다. 따라서 패턴에있는 모든 것을 사용하십시오.

지나치게 강조 할 수 없습니다. 물론 당신이 그러한 것들을 당신의 패턴으로 사용하지 않는다면, 종종 악몽을 일으킬 것입니다. 그러나 당신 그들을 사용 한다면 , 당신은 필요하지 않습니다.

다음은 현대적인 문법 패턴의 또 다른 예입니다.이 구문은 RFC 5322 구문 분석을위한 것입니다 : 5.10.0;

$rfc5322 = qr{

   (?(DEFINE)

     (?<address>         (?&mailbox) | (?&group))
     (?<mailbox>         (?&name_addr) | (?&addr_spec))
     (?<name_addr>       (?&display_name)? (?&angle_addr))
     (?<angle_addr>      (?&CFWS)? < (?&addr_spec) > (?&CFWS)?)
     (?<group>           (?&display_name) : (?:(?&mailbox_list) | (?&CFWS))? ; (?&CFWS)?)
     (?<display_name>    (?&phrase))
     (?<mailbox_list>    (?&mailbox) (?: , (?&mailbox))*)

     (?<addr_spec>       (?&local_part) \@ (?&domain))
     (?<local_part>      (?&dot_atom) | (?&quoted_string))
     (?<domain>          (?&dot_atom) | (?&domain_literal))
     (?<domain_literal>  (?&CFWS)? \[ (?: (?&FWS)? (?&dcontent))* (?&FWS)?
                                   \] (?&CFWS)?)
     (?<dcontent>        (?&dtext) | (?&quoted_pair))
     (?<dtext>           (?&NO_WS_CTL) | [\x21-\x5a\x5e-\x7e])

     (?<atext>           (?&ALPHA) | (?&DIGIT) | [!#\$%&'*+-/=?^_`{|}~])
     (?<atom>            (?&CFWS)? (?&atext)+ (?&CFWS)?)
     (?<dot_atom>        (?&CFWS)? (?&dot_atom_text) (?&CFWS)?)
     (?<dot_atom_text>   (?&atext)+ (?: \. (?&atext)+)*)

     (?<text>            [\x01-\x09\x0b\x0c\x0e-\x7f])
     (?<quoted_pair>     \\ (?&text))

     (?<qtext>           (?&NO_WS_CTL) | [\x21\x23-\x5b\x5d-\x7e])
     (?<qcontent>        (?&qtext) | (?&quoted_pair))
     (?<quoted_string>   (?&CFWS)? (?&DQUOTE) (?:(?&FWS)? (?&qcontent))*
                          (?&FWS)? (?&DQUOTE) (?&CFWS)?)

     (?<word>            (?&atom) | (?&quoted_string))
     (?<phrase>          (?&word)+)

     # Folding white space
     (?<FWS>             (?: (?&WSP)* (?&CRLF))? (?&WSP)+)
     (?<ctext>           (?&NO_WS_CTL) | [\x21-\x27\x2a-\x5b\x5d-\x7e])
     (?<ccontent>        (?&ctext) | (?&quoted_pair) | (?&comment))
     (?<comment>         \( (?: (?&FWS)? (?&ccontent))* (?&FWS)? \) )
     (?<CFWS>            (?: (?&FWS)? (?&comment))*
                         (?: (?:(?&FWS)? (?&comment)) | (?&FWS)))

     # No whitespace control
     (?<NO_WS_CTL>       [\x01-\x08\x0b\x0c\x0e-\x1f\x7f])

     (?<ALPHA>           [A-Za-z])
     (?<DIGIT>           [0-9])
     (?<CRLF>            \x0d \x0a)
     (?<DQUOTE>          ")
     (?<WSP>             [\x20\x09])
   )

   (?&address)

}x;

놀랍지 않고 훌륭하지 않습니까? 기본 구조를 잃지 않고 BNF 스타일 문법을 코드로 직접 변환 할 수 있습니다!

현대식 문법 패턴으로는 여전히 충분하지 않다면 Damian Conway의 화려한 Regexp::Grammars모듈 은 뛰어난 디버깅과 함께 더욱 깔끔한 구문을 제공합니다. 다음은 RFC 5322 리 캐스트를 해당 모듈의 패턴으로 구문 분석하는 동일한 코드입니다.

#!/usr/bin/perl

use strict;
use warnings;
use 5.010;
use Data::Dumper "Dumper";

my $rfc5322 = do {
    use Regexp::Grammars;    # ...the magic is lexically scoped
    qr{

    # Keep the big stick handy, just in case...
    # <debug:on>

    # Match this...
    <address>

    # As defined by these...
    <token: address>         <mailbox> | <group>
    <token: mailbox>         <name_addr> | <addr_spec>
    <token: name_addr>       <display_name>? <angle_addr>
    <token: angle_addr>      <CFWS>? \< <addr_spec> \> <CFWS>?
    <token: group>           <display_name> : (?:<mailbox_list> | <CFWS>)? ; <CFWS>?
    <token: display_name>    <phrase>
    <token: mailbox_list>    <[mailbox]> ** (,)

    <token: addr_spec>       <local_part> \@ <domain>
    <token: local_part>      <dot_atom> | <quoted_string>
    <token: domain>          <dot_atom> | <domain_literal>
    <token: domain_literal>  <CFWS>? \[ (?: <FWS>? <[dcontent]>)* <FWS>?

    <token: dcontent>        <dtext> | <quoted_pair>
    <token: dtext>           <.NO_WS_CTL> | [\x21-\x5a\x5e-\x7e]

    <token: atext>           <.ALPHA> | <.DIGIT> | [!#\$%&'*+-/=?^_`{|}~]
    <token: atom>            <.CFWS>? <.atext>+ <.CFWS>?
    <token: dot_atom>        <.CFWS>? <.dot_atom_text> <.CFWS>?
    <token: dot_atom>        <.CFWS>? <.dot_atom_text> <.CFWS>?
    <token: dot_atom_text>   <.atext>+ (?: \. <.atext>+)*

    <token: text>            [\x01-\x09\x0b\x0c\x0e-\x7f]
    <token: quoted_pair>     \\ <.text>

    <token: qtext>           <.NO_WS_CTL> | [\x21\x23-\x5b\x5d-\x7e]
    <token: qcontent>        <.qtext> | <.quoted_pair>
    <token: quoted_string>   <.CFWS>? <.DQUOTE> (?:<.FWS>? <.qcontent>)*
                             <.FWS>? <.DQUOTE> <.CFWS>?

    <token: word>            <.atom> | <.quoted_string>
    <token: phrase>          <.word>+

    # Folding white space
    <token: FWS>             (?: <.WSP>* <.CRLF>)? <.WSP>+
    <token: ctext>           <.NO_WS_CTL> | [\x21-\x27\x2a-\x5b\x5d-\x7e]
    <token: ccontent>        <.ctext> | <.quoted_pair> | <.comment>
    <token: comment>         \( (?: <.FWS>? <.ccontent>)* <.FWS>? \)
    <token: CFWS>            (?: <.FWS>? <.comment>)*
                             (?: (?:<.FWS>? <.comment>) | <.FWS>)

    # No whitespace control
    <token: NO_WS_CTL>       [\x01-\x08\x0b\x0c\x0e-\x1f\x7f]

    <token: ALPHA>           [A-Za-z]
    <token: DIGIT>           [0-9]
    <token: CRLF>            \x0d \x0a
    <token: DQUOTE>          "
    <token: WSP>             [\x20\x09]

    }x;

};


while (my $input = <>) {
    if ($input =~ $rfc5322) {
        say Dumper \%/;       # ...the parse tree of any successful match
                              # appears in this punctuation variable
    }
}

거기에 좋은 물건을 많이입니다 perlre 맨 페이지는 하지만, 기본적인 정규 표현식 디자인 기능에서이 획기적으로 개선 혼자 펄에 한정되는 것은 있습니다. 실제로 pcrepattern 맨은 쉽게 읽기, 그리고 같은 지역을 커버 할 수있다.

현대의 패턴은 유한 한 오토마타 수업에서 배운 원시적 인 것들과 거의 공통점이 없습니다.


9
예! 예! 마지막으로 누군가는 x 수정자를 사용하여 읽을 수있는 정규 표현식을 보여주는 훌륭한 예를 보여줍니다. 나는 그것이 실제로 존재한다는 사실을 아는 사람이 거의 없다는 것을 믿을 수 없다.
Shabbyrobe

1
@Shabbyrobe : 그것은 단지 아닙니다 /x. (?&name)내부 정규식 서브 루틴 과 함께 문법적으로 문법을 사용하여 실제로 빛을 발합니다.
tchrist

+1 항상 새로운 것을 배웁니다. PCRE에 정의에 대한 "거짓"조건이 있다는 것을 몰랐습니다.
NikiC

5
파이썬도 비슷하게 re.VERBOSE깃발을 가지고 있습니다.
기계 달팽이

3
그냥 Gunna로 가서 정규 표현식을 사용하기 위해 사람들이 갈 길이에 놀랐습니다.
Slater Victoroff

68

정규 표현식은 훌륭한 도구이지만 사람들은 "이봐 요, 정말 훌륭한 도구입니다. X를하기 위해 사용할 것입니다!" 여기서 X는 다른 도구 (보통 파서)에 더 좋은 것입니다. 드라이버 문제가 필요한 해머를 사용하는 것이 표준입니다.


4
대부분의 파서-어휘 분석기-여전히 정규 표현식을 사용하여 내용을 파싱한다는 것을 기억하십시오 :-)
Jasper Bekkers

62
파서가 정규 표현식을 사용한다고 말하는 것은 파서가 할당 문을 사용하는 것과 같습니다. 그것들이 어떻게 사용되는지 볼 때까지 아무런 의미가 없습니다.
Chas. Owens

24
파서가 더 좋을 때 RegEx를 사용하는 것은 성가신 일입니다. 언어의 표준 문자열 찾기 또는 바꾸기 기능이 작동 할 때 (일반적으로 선형 시간으로) RegEx를 사용하면 용서할 수 없습니다.
jmucchiello 2019

1
동의, RegEx는 모든 거래의 잭이어야하기 때문에 처리 오버 헤드가 엄청납니다. RegEx 엔진을 사용하는 것이 쉽다고해서 반복 파서 (개발자 의존 임계 값)보다 나은 솔루션이라는 의미는 아닙니다. 내가 가장 좋아하는 예제 중 하나 인 PHP split($pattern,$string)explode($delimiter,$string)비교할 때-고맙게도 전자는 감가 상각되고 있지만, 나중에 코드의 힘만 필요할 때 많은 코드가 전자를 사용했습니다. Aggreed, RegEx는 몇 가지 작업을 수행하기 쉬운 도구를 제공하지만 정규 표현식의 모든 기능이 필요하지 않은 경우
Rudu

4
어휘 분석기 는 실제로 정규식을 사용할 수 있습니다. 그것들은 토크 나이저로도 알려져 있지만 구문 분석기 (또는 파서) 는 아닙니다 . 복잡하고 충분한 문자열을 읽으려면 토크 나이저를 사용하여 문자열을 토큰으로 읽습니다 (아마도 토큰 화 프로그램에 따라 정규 표현식이있을 수도 있음). 이 토큰은 구문 분석기로 전달되어야하며 정규 규칙이 아닌 문법 규칙으로 처리됩니다.
Axel

53

정규 표현식을 정기적으로 사용하는 사람은 누구나 유닉스 배경을 가지고 있으며 RE를 grep, sed, awk 및 Perl과 같은 일류 프로그래밍 구성으로 취급하는 도구를 사용합니다. 정규 표현식을 사용하는 데 필요한 구문 오버 헤드가 거의 없기 때문에 생산성이 향상됩니다.

반대로 RE가 외부 라이브러리 인 언어를 사용하는 프로그래머는 정규식이 테이블에 가져올 수있는 것을 고려하지 않는 경향이 있습니다. 프로그래머의 "시간 비용"은 너무 높기 때문에 a) RE는 훈련의 일부로 나타나지 않았거나 b) RE와 관련하여 "생각"하지 않고보다 친숙한 패턴으로 돌아 가기를 선호합니다.


11
그래, 라이브러리를 사용하여 정규식 구문을 장황하게 만드는 파이썬을 결코 용서하지 않았다. 나는 그것이 정신 이상이라고 생각합니다.
Slikts

7
나는 유닉스 배경에서 왔으며 sed, awk & perl로드를 사용했으며 물론 많은 grepping을 수행했지만 정규 표현식을 사용할 때 쓰기 전용 해킹이므로 유지 관리가 싫어 질 것입니다. 쉘 스크립트 / 한 번의 타이머에는 좋지만 실제 작업에는 데이터를 저장하는 것뿐만 아니라 명확한 구문으로 적절한 토크 나이저 / 렉서 / 파서를 사용합니다. 내가 가장 좋아하는 것은 모두 / 무엇이든, 깨끗하게 + 스스로 최적화 할 수 있습니다. 나는 처음부터 약간의 자제력이 나중에 노력을 덜 의미한다는 어려운 방법을 배웠습니다. 정규 표현식은 키보드의 순간이며 눈살의 수명입니다.
AndrewC

44

정규식을 사용하면 사용자 지정 유한 상태 머신 (FSM)을 간단한 방식으로 작성하여 일련의 입력을 처리 할 수 ​​있습니다. 정규식 사용이 어려운 이유는 두 가지 이상 있습니다.

  • 구식 소프트웨어 개발에는 많은 계획, 종이 모델 및 신중한 생각이 필요합니다. 정규 표현식은이 모델에 매우 적합합니다. 효과적인 표현식을 제대로 작성하려면 FSM의 경로를 시각화하여 많은 것을 쳐다 봐야합니다.

    최신 소프트웨어 개발자는 코드를 망치고 디버거를 사용하여 실행 단계를 수행하여 코드가 올바른지 확인합니다. 정규 표현식은이 작업 스타일을 잘 지원하지 않습니다. 정규 표현식의 하나의 "실행"은 사실상 원자 연산입니다. 디버거에서 단계별 실행을 관찰하기는 어렵습니다.

  • 실수로 의도 한 것보다 더 많은 입력을받는 정규식을 작성하는 것은 너무 쉽습니다. 정규 표현식의 값은 실제로 유효한 입력과 일치하지 않으며 유효 하지 않은 입력과 일치하지 않습니다 . 정규 표현식에 대해 "음성 테스트"를 수행하는 기술은 그다지 진보되지 않았거나 최소한 널리 사용되지는 않습니다.

    이것은 정규 표현식을 읽기 어렵다는 점으로갑니다. 정규식을 보는 것만으로, 거부되어야하지만 실수로 허용되는 모든 가능한 입력을 시각화하는 데 많은 집중이 필요합니다. 다른 사람의 정규 표현식 코드 를 디버깅하려고 시도한 적이 있습니까?

오늘날 소프트웨어 개발자들 사이에서 정규 표현식을 사용하는 것에 대한 저항이 있다면, 나는 주로이 두 가지 요인 때문이라고 생각합니다.



15
perl -Mre = debug -e "q [aabbcc] = ~ / ab * [cd] /"
Brad Gilbert

15
나는 플라잉 스파게티 몬스터를 생각하지 않고서도 약어 "FSM"을 볼 수 없다고 생각합니다.
초라한

4
@ 초라한 : 나는 기분을 상하게하지 않습니다. 원하는 경우 결정적 유한 자동 마마 톤 (DFA)을 사용할 수 있습니다.
Bill Karwin

37

사람들은 정규 표현이 어렵다고 생각하는 경향이 있습니다. 그들이 잘못 사용하고 있기 때문입니다. 의견, 들여 쓰기 또는 명명 된 캡처없이 복잡한 원 라이너를 작성합니다. 주석, 들여 쓰기 또는 별명없이 복잡한 SQL 표현식을 한 줄에 넣지 않습니까? 예, 많은 사람들에게 이해가되지 않습니다.

당신의 작업이있는 경우 그러나, 무엇이든 (... 거기 거의 모든 웹 응용 프로그램) 텍스트를 구문 분석과 함께 할을하고 정규 표현식을 모르는, 당신은 당신의 일에 빨아 당신은 당신의 자신의 시간을 낭비하고의 당신의 고용주. 거기에 당신이 알아야 할 것들에 관한 모든 것을 가르쳐 줄 훌륭한 자료 가 있습니다.


2
차이점은 여러 공간이 정규 표현식에서 의미가 있다는 것입니다. 다른 언어에서는 그렇지 않으므로 일반적으로 하나의 라이너입니다 (때로는 여러 줄로 줄 바꿈).
Rado

14
@Rado : 예를 들어 Perl x은 공백을 무시하게 하는 정규 표현식에 대한 수정자를 가지고 있습니다. 이를 통해 정규 표현식을 몇 줄에 넣고 주석을 추가 할 수 있습니다.
Nathan Fellman

9
마찬가지로 파이썬에는 re.X일명 re.VERBOSE있습니다.
Craig McQueen

2
마찬가지로 xtcl 의 수정 자입니다. tcl은 다른 언어와 달리 PCRE를 사용하지 않기 때문에 꽤 표준 적이라고 생각합니다.
slebetman

2
@AndrewC이 게시물이 얻을 수있는 가장 큰 오해 중 하나입니다.
Jasper Bekkers

28

그들은 일반적으로 받아 들여지는 IDE에서 가장 인기있는 학습 도구가 없기 때문에 : 정규식 마법사가 없습니다. 자동 완성조차도 아닙니다. 모든 것을 혼자서 코딩해야합니다.


3
그런 다음 잘못된 IDE를 사용하고 있습니다 ... 심지어 텍스트 편집기에서도 정규식 힌트를 제공합니다.
CurtainDog

1
참고로 Expresso와 Regex Coach는 정규식을 작성하는 데 매우 유용한 도구입니다.
Mun

22
세계에서 어떻게 정규 표현식을 자동 완성 하시겠습니까?
AmbroseChapel

3
EditPad Pro에는 검색 상자에 정규 표현식에 대한 구문 강조 표시가 있지만 도움이되는 것보다 더 성가시다. 그러나 나는 대괄호가 없을 때 알려주는 것에 감사합니다. 특히 괄호는 추적하는 곰일 수 있습니다.
Alan Moore

2
@AmbroseChapel-이 토론에 몇 년 늦었습니다. 그러나 regexhero.net/tester 에서 자동 완성 메커니즘을 만들었습니다. round (), square []또는 curly {}brackets 안에있는 일반적인 구조로 시작 됩니다. 백 슬래시에서도 작동합니다.
Steve Wortham


16

나는 그들이 논란의 여지가 없다고 생각합니다.

또한 당신이 자신의 질문에 대답했다고 생각합니다. 왜냐하면 모든 곳에서 사용하는 것이 어리 석다는 것을 지적하기 때문입니다 ( 모든 것이 정규 언어는 아닙니다 ) 2 또는 전혀 사용 하지 않는 것이 좋습니다. 프로그래머는 정규 표현식이 코드에 도움이되거나 코드를 손상시키는시기를 현명하게 결정해야합니다. 이러한 결정에 직면 할 때 명심해야 할 두 가지 중요한 사항은 유지 관리 성 (가독성을 의미 함)과 확장 성입니다.

특히 그들에게 반대되는 사람들에게는, 그것들을 올바르게 사용하는 법을 배운 적이 없다고 생각합니다. 적절한 튜토리얼로 몇 시간 만 소비하는 대부분의 사람들이이를 파악하고 매우 빠르게 유창하게 될 것이라고 생각합니다. 시작 위치에 대한 제안은 다음과 같습니다.

http://docs.python.org/howto/regex

그 페이지가 파이썬의 맥락에서 정규 표현식에 대해 이야기하지만 정보가 다른 곳에서도 매우 적용 가능하다는 것을 알았습니다. 파이썬 고유의 몇 가지 사항이 있지만 명확하게 기억되고 기억하기 쉽다고 생각합니다.



@DMan 감사합니다. 내 답변을 수정하여 반영하겠습니다.
allyourcode

11

정규 표현식은 숫자에 대한 산술 연산자를 문자열로 나타내며 논란의 여지가 없다고 생각합니다. 제 자신과 같은 상당히 많은 OO 활동가 조차도 (줄보다 다른 물체를 선택하는 경향이 있음) 거부하기가 어려울 것이라고 생각합니다.


7

문제는 정규식이 잠재적으로 너무 강력하여 다른 것을 사용해야하는 일을 할 수 있다는 것입니다.

좋은 프로그래머는 어디에서 사용하지 않아야하는지 알아야합니다. 일반적인 예는 비정규 언어를 구문 분석 하는 것입니다 (언어가 정규인지 여부 결정 참조 ).

처음에는 실제 정규 표현식 (확장자 없음)으로 제한하면 잘못 될 수 없다고 생각합니다 . 일부 확장 프로그램은 인생을 조금 더 쉽게 만들 수 있지만 실제 정규 표현식 으로 표현하기 어려운 것을 발견 하면 정규 표현식이 올바른 도구가 아니라는 것을 나타낼 수 있습니다.


5

왜 goto가 논란의 여지가 있는지 묻고있을 것입니다.

기본적으로, 당신이 "명백한"힘을 많이 얻게되면 사람들은 최선의 선택이 아닌 상황에서 그들을 학대하는 경향이 있습니다. 예를 들어 정규 표현식에서 CSV 또는 XML 또는 HTML을 구문 분석하도록 요청하는 사람들의 수는 놀랍습니다. 작업에 대한 잘못된 도구입니다. 그러나 일부 사용자는 어쨌든 정규식을 사용해야한다고 주장합니다.

개인적으로 나는 행복한 매체를 찾으려고 노력합니다. 정규식은 자신이 좋아하는 것에 사용하고 최적이 아닐 때는 피하십시오.

정규식은 여전히 ​​CSV, XML, HTML 등을 구문 분석하는 데 사용될 수 있습니다. 그러나 일반적으로 단일 정규식에는 없습니다.


물론 하나의 정규식으로 이러한 형식을 구문 분석 할 수 있습니다. 정규의 힘입니다. 아기! 당신이 그것을 원하든 원하지 않든, 전적으로 다른 문제입니다.
재스퍼

4

나는 논쟁의 여지가 올바른 단어라고 생각하지 않습니다.

그러나 사람들이 "그런 문자열 조작을하기 위해 필요한 정규 표현식은 무엇입니까?"라고 말하는 많은 사례를 보았습니다. XY 문제입니다.

다시 말해, 정규 표현식이 필요한 것으로 가정했지만, perl의 tr ///와 같은 번역 인 split ()을 사용하는 것이 더 나을 것입니다. 단지 index ().


4

이것은 흥미로운 주제입니다.
많은 정규 표현식 애호가들은 공식의 간결함과 효율성을 혼동하는 것 같습니다.
또한 많은 생각이 필요한 정규 표현식은 저자에게 엄청난 만족감을 가져다줍니다.

그러나 ... 정규 표현식은 성능이 문제가되지 않고 Perl에서 텍스트 출력을 빠르게 처리해야 할 때 매우 편리합니다. 또한 성능 문제 이지만 버그가 많거나 덜 효율적인 수제 알고리즘을 사용하여 정규식 라이브러리를 이길 시도하지 않는 것이 좋습니다.

예를 들어 정규 표현식이 부당하게 비판받는 데에는 여러 가지 이유가 있습니다.

  • 최상위를 만드는 것이 분명하지 않기 때문에 정규 표현식이 효율적이지 않습니다.
  • 일부 프로그래머는 정규 표현식을 여러 번 사용하기 위해 한 번만 컴파일하는 것을 "잊어 버렸습니다"(Java의 정적 패턴처럼)
  • 일부 프로그래머는 시행 착오 전략을 시도합니다 -정규 표현식으로 훨씬 적게 작동합니다!

4

내가 생각하는 것은 정규식 학습과 정규식을 유지하는 것이 인기가 없다는 것입니다. 대부분의 개발자는 게 으르거나 대부분은 외부 라이브러리를 사용하여 구문 분석 작업을 수행합니다. 답변은 Google에 의존하고 포럼에서도 요청합니다. 그들의 문제에 대한 완전한 코드. 그러나 정규식을 구현하거나 수정 / 유지 보수 할 때는 실패합니다.

"친구가 정규식을 사용하여 HTML을 구문 분석하지 못하게한다"라는 인기있는 문구가 있습니다.

그러나 내가 걱정하는 한 정규식을 사용하여 완전한 HTML 파서를 만들었고 정규식이 속도와 메모리 측면에서 HTML 문자열을 구문 분석하는 것이 더 좋습니다.


2
나는 게으른 것처럼 대부분의 개발자를 작성하는 것이 불쾌하다고 생각합니다. 나는 그 구문이 매우 비밀스럽고 직관적이지 않으며, 시작에 대한 문제로 가득 차 있다고 말하며, 이는 진입 장벽을 높인다. 같은 이유로 Perl은 많은 사람들에게 "나쁜"평판을 가지고 있지만 매우 강력한 언어이기도합니다. 기호를 알기 전에 수학적 표현을 읽는 것과 같습니다. 어리석은 일이며 개발자는 해당 구문을 배우는 데 도움이 될 것임을 알기 위해 사 법적이어야합니다.
Katastic Voyage

당신은 것입니다 HTML은 정규 언어가 아니기 때문에 HTML에서 엣지 케이스를 놓친다. HTML의 알려진 부분 집합을 구문 분석하는 것이 안전합니다
Boyang

2

정규 표현은 자신을 포함하여 많은 사람들에게 심각한 미스터리입니다. 그것은 잘 작동하지만 수학 방정식을 보는 것과 같습니다. 누군가가 http://regexlib.com/ 에서 다양한 정규식 함수의 통합 된 위치를 최종적으로 만들었음에도 불구하고 기쁘다 . 이제 Microsoft는 문자를 제거하거나 날짜를 필터링하는 것과 같은 일반적인 작업을 자동으로 수행하는 정규식 클래스 만 만들면됩니다.


2
요점이 없습니다. 정규 표현식의 개념은 당신이 그것들을 배우는데 어느 정도의 시간을 투자하고 당신이 끝났을 때 더 이상 마법의 "날짜 읽기"수업이 필요 없다는 것입니다. 대신 정규 표현식에 거의 노력이 들지 않습니다. 또한, "mm-dd-yyyy"또는 "mm-yyyy / dd"에 대해 하나를 작성하는 것처럼 "yyyy / mm / dd"에 대해 하나를 작성하는 데 적은 노력이 필요합니다. 자주 발생하지는 않지만, 마법 계급이 결코 할 수없는 일을 어떻게 할 수 있는지 보여주는 예입니다. "
Jasper

1

나는 때때로 정규 표현식이 귀중한 것을 발견합니다. "퍼지"검색을 수행해야 할 때 대체 할 수 있습니다. 데이터가 다양하고 특정 임의성을 가질 수있는 경우 그러나 간단한 검색 및 바꾸기 또는 문자열 확인이 필요한 경우 정규식을 사용하지 않습니다. 나는 많은 사람들을 알고 있지만 모든 것을 위해 그것을 사용합니다. 그것은 논쟁입니다.

벽에 압정을 넣으려면 망치를 사용하지 마십시오. 그렇습니다, 그러나 그것은 당신이 망치를 얻을 때, 벽에 20 개의 압정을 넣을 수있었습니다.

정규 표현식은 의도 한대로 사용되어야합니다.


0

정규 표현식이 필수 도구라고 생각하지만 가장 성가신 것은 구현이 다르다는 것입니다. 구문, 수정 자 및 특히 "탐욕"의 약간의 차이는 문제를 혼란스럽게 만들 수 있으며 시행 착오가 필요하고 때로는 수수께끼 같은 버그가 발생합니다.


정규 표현식 구현은 최대 일치에 대한 접근 방식이 어떻게 다른가요? 가장 왼쪽에서 가장 의미 와 가장 왼쪽에서 가장 큰 의미의 차이를 의미합니까? 그것이 내가 아는 유일한 차이점입니다. 즉, 탐욕이 열망을 능가하는지 아니면 그 반대인지 .
tchrist

0

어떤 경우에는 그것들을 사용해야한다고 생각합니다. 예를 들어, 어휘 분석기를 작성하십시오.

제 생각에 이것은 정규 표현식을 작성할 수있는 사람들과 그렇지 않은 사람들에 대한 관점입니다. 개인적으로 이것은 사용자가 경고하는 자바 스크립트 또는 서버 측 언어와 같이 폼의 입력을 유효하게하는 좋은 생각이라고 생각합니다.


0

나는 그것이 프로그래머들 사이에서 덜 알려진 기술이라고 생각합니다. 따라서 널리 받아 들여지지는 않습니다. 또한 기술 관리자가 아닌 사람이 코드를 검토하거나 작업을 검토하면 정규 표현식이 매우 나쁩니다. 완벽한 정규 표현식을 작성하는 데 몇 시간을 소비하며, 코드를 거의 작성하지 않았다고 생각하는 모듈에 대한 점수는 거의 없습니다. 또한 다른 곳에서 말했듯이 정규 표현식을 읽는 것은 매우 어려운 작업입니다.


1
정규 표현식을 읽는 프로그래머는 공백, 주석, 영숫자 식별자 및 지연된 실행을 통해 포함 된 서브 루틴을 사용하지 못한 경우에만 어려운 작업입니다. 즉, 일반 프로그래밍에 적용 할 수있는 모든 소프트웨어 엔지니어링 기술도 정규식으로 따라야합니다. 이러한 원칙을 무시하면 작가는 전문 코드를 생성하지 않습니다.
tchrist

관리자가 "프로그래밍의 진정한 영웅은 부정적인 코드를 작성하는 사람입니다."
Rajeev

관리자가 900 줄의 어셈블러에서 작업 한 doofus 동료를 칭찬하면서 3 줄의 코드 (regexp 포함)로 작업을 수행하기 위해 당신을 쫓아 버릴 경우 ... 나는 새로운 일자리를 찾는 것이 좋습니다.
Phil Perry 22

0

컴파일러 정의를 위해 lex 및 yacc에서 사용되는 것과 같은 적절한 정규식 시스템은 훌륭하고 유용하며 깨끗합니다. 이러한 시스템에서 표현식 유형은 다른 유형으로 정의됩니다. 펄과 sed 코드 (예 : 등)에서 흔히 볼 수있는 '거의'(쓰레기) 끔찍한 기형의 읽을 수없는 라인 노이즈 거대한 1- 라이너 정규식입니다.


-4

정규식에 대한 가장 유효하고 일반적인 사용법은 전자 메일 주소 형식 유효성 검사입니다.

그것은 좋은 응용입니다.

TextPad에서 일회성으로 정규 표현식을 무수히 사용하여 플랫 파일을 마사지하고 csv 파일을 만들고 SQL 삽입 문을 작성했습니다.

잘 작성된 정규식은 너무 느려서는 안됩니다. 대체 호출에 대한 많은 호출과 같은 대안은 훨씬 느린 옵션입니다. 한 번에 할 수도 있습니다.

많은 상황에서 정확히 정규 표현식을 요구하지만 다른 것은 없습니다.

특수한 비 인쇄 문자를 무해한 문자로 바꾸는 것도 좋은 방법입니다.

물론 정규 표현식을 과도하게 사용하여 유지 관리 성을 저하시키는 코드베이스가 있다고 생각할 수 있습니다. 나는 그것을 본 적이 없다. 정규 표현식을 충분히 사용하지 않아 코드 검토자가 실제로 피했습니다.


10
경험에 따르면 정규 표현식은 실제로 전자 메일 주소 형식 유효성 검사를위한 매우 열악한 도구입니다. 정규 표현식으로 구현 된 완전한 형식의 유효성 검사기는 수백 자의 괴물이며 대부분의 사람들이 5 분 동안 작성하는 짧은 "충분한"유효성 검사기는 대부분 유효하고 전달 가능한 주소의 큰 범주를 거부합니다.
Dave Sherohman

나중에 친구의 소리가 들립니다. 나는 "충분히 좋은"것에 대해 이야기하고 있었고, 큰 무리는 이론 상으로는 클 수 있지만, 짧은 표현으로 얻는 범위의 백분율을 고려하십시오. 나도 괴물을 보았지만 당신의 우아한 대안은 무엇입니까?
Chris Morley

2
나는 \ w @ \ w +. \ w +와 같은 것을 사용하여 속도가 중요하고 몇 가지 오 탐지 또는 오 탐지가 중요하지 않은 거대한 파일 디렉토리에서 이메일 주소를 빨리 찾았습니다. 그러나 이메일 주소를 확인하는 가장 좋은 방법은 이메일을 보내는 것 같습니다.
RossFabricant

예, 주소 사양이
불분명합니다.

@Nick, @Dave : 메일 주소 확인 이 불쾌 할 필요는 없습니다.
tchrist
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.