원본을 유지하면서 문자열에서 Perl 대체를 어떻게 수행합니까?


180

Perl에서 정규 표현식을 사용하여 문자열을 바꾸고 원래 변수를 변경하지 않고 다른 변수에 값을 저장하는 좋은 방법은 무엇입니까?

나는 보통 문자열을 새 변수에 복사 한 다음 s///새 문자열을 대체 하는 정규식에 바인딩 하지만 더 좋은 방법이 있는지 궁금합니다.

$newstring = $oldstring;
$newstring =~ s/foo/bar/g;

답변:


257

이것은 원본을 변경하지 않고 문자열의 수정 사본을 얻는 데 항상 사용한 관용구입니다.

(my $newstring = $oldstring) =~ s/foo/bar/g;

perl 5.14.0 이상에서는 새로운 /r 비파괴 대체 수정자를 사용할 수 있습니다 .

my $newstring = $oldstring =~ s/foo/bar/gr; 

참고 : 위의 솔루션도 작동하지 g않습니다. 또한 다른 수정 자와도 작동합니다.


6
사용중인 엄격한 여부. 변수의 최소 범위 지정 ++
ysth September

같은 my $new = $_ for $old =~ s/foo/bar;것이 효과 가 있는지 궁금합니다 .
Benoit

2
@Benoit, 나는 s/foo/bar/ for my $newstring = $oldstring;그것이 작동 한다는 것을 믿지만 , 훨씬 이상합니다.
ikegami

43

진술 :

(my $newstring = $oldstring) =~ s/foo/bar/g;

다음과 같습니다.

my $newstring = $oldstring;
$newstring =~ s/foo/bar/g;

또는 Perl 5.13.2에서 /r비파괴 대체를 수행하는 데 사용할 수 있습니다 .

use 5.013;
#...
my $newstring = $oldstring =~ s/foo/bar/gr;

3
g최고의 정규 표현식 을 잊어 버렸습니까 ?
mareoraft

23

아래에서 다음 use strict과 같이 말합니다.

(my $new = $original) =~ s/foo/bar/;

대신에.


10

한 줄짜리 솔루션은 좋은 코드보다 shibboleth로 더 유용합니다. 좋은 Perl 코더는 그것을 알고 이해하지만, 시작하는 두 줄의 copy-and-modify couplet보다 훨씬 덜 투명하고 읽기 쉽습니다.

다시 말해서, 이것을하는 좋은 방법은 이미 하고 있는 방법 입니다. 가독성에 대한 불필요한 결정은 승리가 아닙니다.


아, 그러나 한 줄 버전은 실수로 잘못된 문자열을 수정해야한다는 오류가 발생하지 않습니다.
ysth

<i> 올바로 실행 된 경우 </ i> 한 줄 버전은 주제가 아닙니다. 그러나 그것은 별도의 문제입니다.
조쉬 밀라 드

9
불필요한 결정이라고 생각할 수 있지만 한 번 사용하기 위해 변수 이름을 두 번 입력해야하는 것은 실패 지점 수의 두 배입니다. 이 언어는 언어를 아는 사람들이 완벽하게 읽을 수 있으며 <i> Learning Perl </ i> 과정에도 있습니다.
brian d foy 2018 년

1

다른 pre-5.14 솔루션 : http://www.perlmonks.org/?node_id=346719 (japhy의 게시물 참조)

그의 접근 방식은 map배열에서도 잘 작동하지만 map임시 배열을 생성 하려면 계단식 배열이 필요합니다 (그렇지 않으면 원본이 수정됩니다).

my @orig = ('this', 'this sucks', 'what is this?');
my @list = map { s/this/that/; $_ } map { $_ } @orig;
# @orig unmodified

1

나는 foo와 bar가 .. 어쨌든 프로그래밍에서 비 설명 적 용어를 꿈꾸는 사람은 누구입니까?

my $oldstring = "replace donotreplace replace donotreplace replace donotreplace";

my $newstring = $oldstring;
$newstring =~ s/replace/newword/g; # inplace replacement

print $newstring;
%: newword donotreplace newword donotreplace newword donotreplace

2
원본과 다른 점은 무엇입니까? (그리고 당신이 원한다고 생각합니다 =~ s.)
Teepeemm

음란 한 실수. 이 코드의 실제 결과는 다음과 같습니다.newword donotnewword newword donotnewword newword donotnewword
파스칼

2
JoGotta가 전통적이고 친숙 foo하고를 사용했다면 bar그의 대답은 정확했을 것입니다. 다시 한 번 입증하는 이유는 관습이 존재하며 교훈은 어려운 방식으로 만 배운다는 것입니다. ;)
Jon

-1

Perl을 쓰면 use strict;선언 할 때에도 한 줄 구문이 유효하지 않다는 것을 알 수 있습니다.

와:

my ($newstring = $oldstring) =~ s/foo/bar/;

당신은 얻는다 :

Can't declare scalar assignment in "my" at script.pl line 7, near ") =~"
Execution of script.pl aborted due to compilation errors.

대신에 한 줄 더 길게 사용했던 구문은 구문 적으로 올바른 방법입니다 use strict;. 나를 위해, 사용 use strict;은 이제 습관입니다. 자동으로합니다. 모두가해야합니다.

#!/usr/bin/env perl -wT

use strict;

my $oldstring = "foo one foo two foo three";
my $newstring = $oldstring;
$newstring =~ s/foo/bar/g;

print "$oldstring","\n";
print "$newstring","\n";

1
당신이 경우 use warnings;대신 -w, 당신은 더 제어 할 : 예를 들어, 당신은 일시적으로 코드 블록에 경고를 해제 할 경우.
glenn jackman
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.