perl qr // 대체
-
11-07-2019 - |
문제
GetOps를 사용하여 사용자 입력을 취하는 작은 프로그램을 작성하고 있으며,이를 기반으로 프로그램은 일부 텍스트와 패턴을 일치 시키거나 일치하는 것에 대한 텍스트를 대체하려고합니다.
내가 가진 문제는 대체 부분을 작동시킬 수 없다는 것입니다. 맨 페이지의 QR // 항목을보고 있습니다. http://perldoc.perl.org/perlop.html#regexp-quote-like-operators 그러나 나는 그것에 운이 좋지 않습니다. 이 경우 문서와 똑같은 코드를 모델링하려고했습니다. 나는 일치 패턴을 컴파일하고 그것을 대체로 대체합니다.
누군가 내가 어디로 가고 있는지 지적 할 수 있습니까? (보안에 대해 너무 걱정하지 마십시오. 이것은 개인적으로 사용하기위한 작은 대본 일뿐입니다)
내가보고있는 내용은 다음과 같습니다.
if($options{r}){
my $pattern = $options{r};
print "\nEnter Replacement text: ";
my $rep_text = <STDIN>;
#variable grab, add flags to pattern if they exist.
$pattern .= 'g' if $options{g};
$pattern .= 'i' if $options{i};
$pattern .= 's' if $options{s};
#compile that stuff
my $compd_pattern = qr"$pattern" or die $@;
print $compd_pattern; #debugging
print "Please enter the text you wish to run the pattern on: ";
my $text = <STDIN>;
chomp $text;
#do work and display
if($text =~ s/$compd_pattern/$rep_text/){ #if the text matched or whatever
print $text;
}
else{
print "$compd_pattern on \n\t{$text} Failed. ";
}
} #end R FLAG
-r "/matt/"-i로 실행하고 텍스트 'matt'에 대체 텍스트 'Matthew'를 입력하면 실패합니다. 왜 이런거야?
편집하다:
답변 주셔서 감사합니다! 정말 도움이되었습니다. 나는 두 가지 제안을 문제에 대한 작업 솔루션으로 결합했습니다. /g 플래그를 조금 다르게 처리해야합니다. 작업 샘플은 다음과 같습니다.
if($options{r}){
my $pattern = $options{r};
print "\nEnter Replacement text: ";
my $rep_text = <STDIN>;
chomp $rep_text;
#variable grab, add flags to pattern if they exist.
my $pattern_flags .= 'i' if $options{i};
$pattern_flags .= 's' if $options{s};
print "Please enter the text you wish to run the pattern on: ";
my $text = <STDIN>;
chomp $text;
#do work and display
if($options{g}){
if($text =~ s/(?$pattern_flags:$pattern)/$rep_text/g){ #if the text matched or whatever (with the g flag)
print $text;
}
else{
print "$pattern on \n\t{$text} Failed. ";
}
}
else{
if($text =~ s/(?$pattern_flags:$pattern)/$rep_text/){ #if the text matched or whatever
print $text;
}
else{
print "$pattern on \n\t{$text} Failed. ";
}
}
} #end R FLAG
해결책
혼돈이 지적했듯이, 당신은 몇 가지 어려움을 겪게됩니다. qr//
. 패턴을 사전 컴파일해야합니까? 그렇지 않다면 이와 같은 전략이 효과가있을 수 있습니다.
my $pattern = 'matt';
my $text = 'Matt';
my $rep_text = 'Matthew';
my $pattern_opts = 'i';
print $text, "\n" if $text =~ s/(?$pattern_opts:$pattern)/$rep_text/;
새 코드에 대한 응답으로 업데이트하십시오: 다음과 같은 접근 방식을 사용하는 것을 고려할 수 있습니다.
my ($orig, $patt, $rep, $flags) = qw(FooFooFoo foo bar ig);
my $make_replacement = $flags =~ s/g// ?
sub { $_[0] =~ s/(?$flags:$patt)/$rep/g } :
sub { $_[0] =~ s/(?$flags:$patt)/$rep/ }
;
if ( $make_replacement->($orig) ){
print $orig;
}
else {
print "Failed...";
}
다른 팁
실행하십시오 -r "matt"
, 아니다 -r "/matt/"
. 옵션 문자열에 패턴 구분자를 공급할 필요가 없으며 실제로는 할 수 없습니다. 따옴표는 당신의 구분자입니다 qr
. 그래서 실제로 찾고 있습니다 matt
주위의 슬래시, 당신이 실행하는 방식, 원하는 것이 아닙니다. 당신은 인용문을 사용하여 Perl에게 패턴 문자열을 소스 코드처럼 취급하도록 지시하려고하지만 불행히도 그렇게 할 수는 없습니다.
다른 옵션에 대해 수행하는 모든 패턴도 작동하지 않습니다. 모든 작업을 수행하려면 Regex를 컴파일하는 방식을 변경해야합니다. 이와 같은 일이 그렇게 할 수 있습니다 /i
그리고 /s
:
my $compd_pattern = qr/$pattern/ or die $@;
$compd_pattern = qr/$compd_pattern/i if $options{i};
$compd_pattern = qr/$compd_pattern/s if $options{s};
을 위한 /g
검색/교체의 대체 버전을 지원해야합니다. /g
유효한 수정자가 아닙니다 qr//
.