regex
  • perl
  • 2012-08-14 3 views 2 likes 
    2

    this 질문에 대한 응답을 시도하는 동안 Perl의 정규식 엔진에서 이상한 동작이 발생했습니다. 정규식과 일치시키려는 2 개의 수량을 포함하는 문자열이 있습니다. 정규식은 "units/ml"문자열 앞의 8 문자와 일치합니다. 나는 두 부대를 모두 잡고 싶다.왜 동일한 정규 표현식을 두 번 실행하면 결과가 달라 집니까?

    use warnings; 
    use strict; 
    my $line = 'some data 100,000 units/ml data 20,000 units/ml data'; 
    my @array; 
    if ($line =~ m/.{8}units\/ml/g) { 
        @array = $line =~ m/.{8}units\/ml/g; 
        print join(' ', @array) . "\n"; 
    } 
    

    출력 : 내가 두 번 라인 6을 실행하면

    20,000 units/ml 
    

    이 할당 라인이 @array하기 :

    이 스크립트는 일치 2를 인쇄

    use warnings; 
    use strict; 
    my $line = 'some data 100,000 units/ml data 20,000 units/ml data'; 
    my @array; 
    if ($line =~ m/.{8}units\/ml/g) { 
        @array = $line =~ m/.{8}units\/ml/g; 
        # Let's run that again, for good measure... 
        @array = $line =~ m/.{8}units\/ml/g; 
        print join(' ', @array) . "\n"; 
    } 
    

    출력 :

    100,000 units/ml 20,000 units/ml 
    

    왜이 두 스크립트가 다른 결과를 산출합니까?

    답변

    4

    이는 if의/g 한정자 때문입니다. if가 스칼라 컨텍스트에서 = ~를 평가하기 때문에 첫 번째 항목 만 일치시킵니다. 그런 다음 if 블록 내부에서 @array 할당은 중단 된 부분부터 검색을 계속합니다. (구문 분석에 유용합니다.)

    추가 일치를 실행하면 문자열의 모든 내용이 이미 일치하므로 목록의 처음부터 다시 시작하고 모든 것을 얻을 수 있습니다.

    if에서 g 플래그를 제거하면 예상대로 작동합니다.

    1

    의 옵션은,이 경우 if 문에서 배열 할당을 평가하는 것입니다 :

    use Modern::Perl; 
    
    my $line = 'some data 100,000 units/ml data 20,000 units/ml data'; 
    my @array; 
    if (@array = $line =~ m/.{8}units\/ml/g) { 
        print join(' ', @array) . "\n"; 
    } 
    

    출력 : 필요한 경우

    100,000 units/ml 20,000 units/ml 
    

    적절한 조치가있는 경우, 취할 수 없음 일치가 발생했습니다.

    +1

    네, 내가 할 줄 것과 아주 가까이처럼 뭔가를 작성해야합니다. 그러나 if 문에 my를 넣을 수 있습니다.'if (my @array = ...) {여기에서 유효한 @array는 유효하지만 여기가 없습니다.} – Tanktalus

    +0

    @Tanktalus - 실제로, 여러분도 할 수 있습니다. +1 – Kenosis

    0

    문제는 여기에있다

    if ($line =~ m/.{8}units\/ml/g) { ... } 
    

    패턴의 다음 발생을 일치하고 다음 글로벌 경기는 그 후

    을 시작해야하는 위치라고 마크를 설정합니다 스칼라 문맥에서 글로벌 경기 패턴과 일치하는 문자는 20,000 units/ml 뿐이므로 한 번만 일치합니다.

    문자열의 모든 숫자 또는 쉼표를 뒤에서 units/ml으로 수집하려면 u는이

    use strict; 
    use warnings; 
    
    my $line = 'some data 100,000 units/ml data 20,000 units/ml data'; 
    
    my @array = $line =~ m|([0-9,]+)\s*units/ml|g; 
    
    print "$_\n" for @array; 
    

    출력

    100,000 
    20,000 
    
    관련 문제