파일 이름에 대시가 포함되어 있으면 Perl에 문제가 있습니다.

파일 이름에 대시가 포함되어 있으면 Perl에 문제가 있습니다.
... | perl -pe "s/([^$filespec]*)($filespec)/ ...

$filespec따라서 대부분의 경우 위의 구조가 잘 작동하는 기능이 있습니다. 하지만파일 이름에 대시가 있는 경우메시지 를 받았습니다 Invalid [] range.

$filespec이러한 구문 분석 오류의 영향을 받지 않는 파일 이름으로 변수가 확장되도록 하려면 어떻게 해야 합니까 ?

답변1

주요 가정 - $filespec일치시키려는 문자 집합입니다. 이것은아니요정규식.

일부 코드를 사용하여 이 문제를 시뮬레이션해 보겠습니다.

filespec = 'z-a'
perl -e 'print "MATCH\n" if "DEF" =~ /$filespec/'

use strict;
use warnings;

my $filespec = 'z-a';

print "Match\n" if "DEF" =~ m/[^$filespec]/ ;

달리기는 줄 수 있다

Invalid [] range "z-a" in regex; marked by <-- HERE in m/[^z-a <-- HERE ]/ at try line 6.

$filespec문제는 정규식의 확장이 m/[^z-a]/. 이 경우 z-a문자 범위가 유효하지 않습니다.

이 문제를 해결하려면 (적어도) -in 을 이스케이프 처리해야 합니다 $filespec. 이것을 사용하면 quotemeta다음과 같이 트릭을 수행할 수 있습니다.

use strict;
use warnings;

my $filespec = quotemeta 'z-a';

print "Match\n" if "DEF" =~ m/[^$filespec]/ ;

출력은 다음과 같습니다

Match

이를 파이프 명령 시뮬레이션에 포함합니다. 첫 번째는 실패한 명령 버전입니다.

filespec='z-a'
perl -e "print qq[MATCH\n] if 'DEF' =~ /[^$filespec]/"

달려가다

Invalid [] range "z-a" in regex; marked by <-- HERE in m/[^z-a <-- HERE ]/ at -e line 1.

이것은 고정 버전입니다.

filespec='z-a'; 
filespec=`perl -e "print quotemeta qq[$filespec]"`
perl -e "print qq[MATCH\n] if 'DEF' =~ /[^$filespec]/"

답변2

괄호 안에 있는 표현식의 대시는 백슬래시 1 로 이스케이프되거나 표현식의 첫 번째 또는 마지막 문자가 아닌 한 범위로 처리됩니다(또는 ^다음 첫 번째 ^또는 마지막 문자 쌍으로 표현되는 경우 수식이 부정됩니다).

예를 들어

[a-z]afrom to의 모든 소문자 와 일치합니다 z (단, 참고 2 참조).

[a\-z], [-az]그리고 모두 , 및 [az-]3개의 문자만 일치합니다 .-az

그리고 @pmqs가 답변에서 지적했듯이 [z-a]이는 잘못된 범위이므로 오류가 발생합니다.

정규 표현식에 하나 이상의 대시가 있는 대괄호 표현식이 포함된 경우 예상대로 작동하도록 수정해야 합니다. 대부분의 경우와 마찬가지로 사용 중인 소프트웨어와 언어 기능을 충분히 이해하여 원하는/기대하는 작업을 수행할 수 있어야 합니다.

man perlre편의 기능과 알아야 할 기타 "문제점"을 포함하여 Perl 정규 표현식에 대해 자세히 알아보려면 리소스를 참조하세요 . 이 매뉴얼 페이지에는 많은 내용이 있으므로 한 번에 모두 이해할 수는 없습니다. 필요할 때 검토하면 앞으로 몇 년 동안 어떻게 작동하는지 더 많이 이해하게 될 것입니다. man perlrequick빠른 참조 및 man perlretut튜토리얼 도 참조하세요 . man perlrecharclassPerl의 문자 클래스 및 대괄호 표현식 에 대한 추가 정보. man perlrebackslashPerl의 백슬래시 및 이스케이프 시퀀스 에 대한 추가 정보.

man(Linux 배포판이나 Unix에 페이지로 사용할 수 있는 Perl 문서가 없으면 perldoc대신 run 명령을 사용하십시오 man(예 perldoc perlre: ).

Perl에는 총 54,000단어의 산문과 예제로 이루어진 5개의 주요 매뉴얼 페이지가 정규식 전용으로 있다는 점을 고려하면(그리고 두 개는 아마도 전혀 필요하지 않을 것입니다: perlregutsPerl 정규식 엔진의 작동 방식을 설명하고 perlreapiPerlre의 플러그인 인터페이스를 설명합니다), 당신은 이것이 복잡한 주제라고 추측하기 시작할 수도 있습니다. 그리고 당신이 옳을 것입니다.


노트:

1 모든 정규식 엔진이 대괄호 표현식 내에서 이스케이프 문자를 지원하는 것은 아닙니다 . Perl은 하지만 대부분은 그렇지 않습니다. 예를 들어 GNU grep의 BRE(기본값 또는 -G) 및 ERE( -E)는 그렇지 않지만 GNU grep의 perl 호환( -P) 정규 표현식은 그렇습니다.

2 [[:alpha:]] 또는 일반 ASCII뿐만 아니라 유니코드 텍스트도 처리할 수 있으므로 일반적으로 알파벳 문자 일치에 더 적합합니다 [[:upper:]]. 영숫자와 동일합니다.[[:lower:]][[:alnum:]]

관련 정보