2014-09-28 2 views
2

이것은 아마도 내 기본적인 오류 일 수 있지만,이 문제에 오래 머물러있어 벽을 위로 몰고 있습니다!

나는 Perl을 사용하여 파이썬 코드 파일을 반복하고 그 변수를 식별하고있다. Perl 정규 표현식을 사용하여 공백 사이에서 영숫자 문자의 부분 문자열을 선택합니다. 정규식이 잘 작동하고 일치하는 줄을 식별하지만 정규식과 일치하는 실제 하위 문자열을 반환하려고하면 $1 캡처 변수는 정의되지 않습니다.

여기 내 정규식 :

if ($line =~ /.*\s+[a-zA-Z0-9]+\s+.*/) { 
    print $line; 
    print $1; 
} 

그리고 여기에 오류가 :

x = 1 
Use of uninitialized value $1 in print at ./vars.pl line 7, <> line 2. 

내가 알고있는 것처럼

$1x를 반환 할 예정이다. 내 코드가 어디에서 잘못 되었습니까?

답변

7

당신은 결과를 캡처하지 않는 : 당신이 x = 1 같은 라인을 일치하고 그것의 두 부분을 얻고 싶은 경우에

if ($line =~ /.*\s+([a-zA-Z0-9]+)\s+.*/) { 

, 당신은에 일치 괄호로 모두를 캡처해야합니다. 허술한 접근 :

if ($line =~ /^\s* (\w+) \s* = \s* (\w+) \s* $/msx) { 
    my $var = $1; 
    my $val = $2; 
} 
3

은 올바른 answerLeeft에 의해 주어졌다 : 당신은 괄호를 사용하여 문자열을 캡처해야합니다. 나는 다른 것을 언급하고 싶었다. 귀하의 코드에서 :

if ($line =~ /.*\s+[a-zA-Z0-9]+\s+.*/) { 
    print $line; 
    print $1; 
} 

.*\s+와 (과) 일치하는 것을 찾으십시오. 이것은 당신이 생각하는 일을하는 것 같지 않습니다. 문자열을 캡처하거나 $&을 사용하여 전체 일치를 캡처하지 않는 한 .*m//과 함께 사용할 필요가 없습니다. 일치 항목은 기본적으로 고정되어 있지 않으며 문자열의 어느 부분과도 일치합니다. 일치 항목을 고정하려면 ^ 또는 $을 사용해야합니다. 예컨대 :

if ('abcdef' =~ /c/)  # returns true 
if ('abcdef' =~ /^c/)  # returns false, match anchored to beginning 
if ('abcdef' =~ /c$/)  # returns false, match anchored to end 
if ('abcdef' =~ /c.*$/) # returns true 

당신이 .*을 사용하여 마지막 예에서 보듯이

상당히 중복, 당신은 앵커를 제거하기 만하면 경기를 얻을 수 있습니다. 아니면 전체 문자열 캡처하기를 원한다면 :

if ('abcdef' =~ /(c.*)$/) # returns true, captures 'cdef' 

또한 $&를 사용할 수에 관계없이 괄호, 전체 경기가 포함되어 있습니다.

부분 단어와 일치하지 않도록 \s+을 사용하고있을 가능성이 큽니다. 단어 경계라는 이름의 이스케이프 시퀀스 인 \b이 있다는 것을 알고 있어야합니다. 이 길이는 길이가 0 인 어설 션으로 주변의 문자가 단어인지 아닌지를 확인합니다. \s+를 사용

'abc cde fgh' =~ /\bde\b/  # no match 
'abc cde fgh' =~ /\bcde\b/ # match 
'abc cde fgh' =~ /\babc/  # match 
'abc cde fgh' =~ /\s+abc/  # no match! there is no whitespace before 'a' 

마지막 예에서 보듯이

은 시작 또는 문자열의 끝에서 실패합니다. \b은 또한 다음과 같은 단어의 일부가 될 수 있습니다 비 단어 문자에서 부분적으로 일치하는 점에 유의 마십시오

'aaa-xxx' =~ /\bxxx/   # match 

이 동작을 원하거나하지 않을 경우 당신은 결정해야합니다.그렇지 않은 경우 \s을 사용하는 대신 (?!\S)의 이중 대소 문자를 사용하는 것이 좋습니다. 이것은 공백이 아닌 것을 찾는 zero-length negative look-ahead 어서션이다. 공백 문자와 문자열의 끝 부분에 적용됩니다. 뒤쪽을 사용하여 반대쪽을 확인하십시오.

마지막으로 [a-zA-Z0-9]을 사용하고 있습니다. \w에는 밑줄 _ (및 다른 단어 문자)도 포함되어 있지만이 값은 \w으로 바꿀 수 있습니다.

그래서 정규식이된다 :

/\b(\w+)\b/ 

또는

/(?<!\S)(\w+)(?!\S)/ 

문서 :