2009-06-25 4 views
0

에 문자열의 여러 인스턴스를 교체 :나는, 같은 파일에 입력 다음 사용 사례 한 펄

Line1 : AA BB CC DD EE 

내가 이것을 대체 할

1 2 3 4 5 

출력

Line1: 1 2 3 4 5 

Perl에서 하나의 정규 표현식에서이 작업을 수행 할 수 있습니까?

나는이 시도하지만

my @arr1 = ("AA", "BB", "CC", "DD", "EE"); 
open F2, $file; 
my $count = 0; 
while (<F2>) { 
    my $str = $_; 
    $str =~ s/$arr[$count]/$count+1/g; 
    print to file 
} 

close(F2); 

이 어떤 아이디어를 내가 제대로 이해한다면, 당신은 번호 모든 단어를 대체 할

답변

2

트릭을하지 않습니다 (모든 단어 후 1 씩 증가) unsucessful이었다 . 다음은 테스트가있는 프로그램입니다.

#!/usr/bin/perl 

use strict; 
use warnings; 
use Test::More qw(no_plan); 

sub replace { 
    my $str=shift; 
    my $count=1; 
    $str=~s/\w+/$count++/ge; 
    return $str; 
} 


is(replace('AA AA DD EE'),'1 2 3 4'); 
is(replace('A B C D E'),'1 2 3 4 5'); 
+0

Test :: More는 어떻게됩니까? –

+0

Nathan : 작동 방식을 테스트합니다. –

+1

@Nathan : Test :: 더 자세히 is() 함수를 가져 오시겠습니까? ;) 그러나 나는 당신과 동의합니다, 간단한 "인쇄 대체 ('AA BB CC DD');" 예를 들어, Test :: More는 아무 것도 추가하지 않습니다. – user55400

2

현재 수행하고 있지 않은 파일을 수정하려면 무엇인가해야합니다. 가장 쉬운 방법은 File::Inplace을 사용하거나 두 번째 파일로 출력하는 것입니다.

또한 배열을 반복하지 않고 파일의 행을 반복하므로 각 행의 $ arr [0] 만 1로 바뀝니다.

use strict; 
    use warnings; 
    use File::Inplace; 

    my @replacees = ("AA", "BB", "CC", "DD", "EE"); 
    my $editor = new File::Inplace(file => "file.txt", regex => "\n"); 
    while (my ($line) = $editor->next_line) { 
    my $count = 1 
    for my $replacee (@replacees) { 
     if ($line =~ m/$replacee/) { 
      $line =~ s/$replacee/$count/g; 
     } 
     $count = $count + 1; 
    } 
    $editor->replace_line($line); 
    } 
    $editor->commit; 
2

동일한 파일에 쓰는 것에 대해서는 Vinko 응답을 참고하십시오.

my @arr1 = ("AA", "BB", "CC", "DD", "EE"); 
my %replacements = map { ($arr1[$_] => $_ + 1) } (0..$#arr1); 
my $regexp = join('|', sort { length($b) <=> length($a) } @arr1); 

open F2, $file; 
while (<F2>) { 
    my $str = $_; 
    $str =~ s/($regexp)/$replacements{$1}/ge; 
    print $str; 
} 
close(F2); 

중요 부품 :

my %replacements = map { ($arr1[$_] => $_ + 1) } (0..$#arr1); 

그것은 @ arr1에서 키 해시를 구축하고, 값이 1 씩 증가 @ arr1에서 주어진 값의 인덱스입니다 문자열을 교체,이 조각을 확인하시기 바랍니다

예를 들어, @ arr1 = ("a", "b", "d", "c")의 경우; 대체율은 다음과 같습니다. ("a"=> 1, "b", => 2, "c"=> 4, "d"=> 3);

my $regexp = join('|', sort { length($b) <=> length($a) } @arr1); 

이것은 @ arr1에서 모든 단어를 찾기위한 기본 정규 표현식을 구축합니다. 정렬 부분은 길이가 내림차순으로 단어를 정렬합니다. 그래서, @ arr1 = ("a", "ba", "bac") $ regexp는 'bac | ba | a'가됩니다.

이 순서는 다른 단어의 접두사가 될 경우 문제가 될 수 있으므로 중요합니다 (본 예에서는 "ba"및 "bac"와 같이).

마지막으로 말하자면 FH로 파일 핸들을 사용하는 것은 다소 실망 스럽습니다. 이러한 파일 핸들러는 전역이며, 좀 더 복잡한 프로그램에서 "흥미로운"문제를 생성합니다.대신 다음과 같이 공개 사용

open my $fh, 'filename'; 

또는 더 나은 아직 :

open my $fh, '<', 'filename'; 
0

첫째, 보정 : 당신이 $str에 결국 읽기 라인을 원하는 경우에

while (<F2>) { 
    my $str = $_; 

이있다 프로세스에 $_이 포함될 이유가 없습니다.

while (my $ str =) {

또한 depesz에 의해 작성된 요점은 전역 bareword 파일 핸들을 패키지화하지 않고 어휘 파일 핸들을 사용해야한다는 것입니다.

지금, 당신의 루프보고 :

my $count = 0; 
while (my $str = <$input_fh>) { 
    $str =~ s/$arr[$count]/$count+1/g; 
    # ... 
} 

@foo의 요소의 수보다 파일의 줄 이상이있을 수 있음을 암시 가정있을 것 같습니다. 어떤 경우에는 $count : $.을 사용하지 않아도됩니다. 당신이 두 번째 줄에 있다고 가정 해보십시오. 코드에서 BB의 모든 항목을 구두 설명과 다른 2으로 바꾸고 싶다고 말합니다.

중요한 점 : 게시하는 모든 코드는 구두 설명과 일치해야합니다.

어쨌든, 여기에 한 가지 방법입니다 :

rty.pl

#!/usr/bin/perl 

use strict; 
use warnings; 

use File::Slurp; 

my ($input) = @ARGV; 

write_file(
    $input, [ 
     map { s/(([A-Z]) \2)/ord($2) - ord('A') + 1/gex; $_ } read_file $input 
    ] 
); 
__END__ 

test.data :

Line1 : AA BB CC DD EE 
Line1 : AA BB CC DD EE 
Line1 : AA BB CC DD EE 
Line1 : AA BB CC DD EE 

$ rty.pl test.data 

test.data 스크립트 호출 후 :

이 => 1, 'BB'=> 2 'CC'=> 3 'DD'=> 4,

내 %의 arr2 = ('AA'를 작동210

Line1 : 1 2 3 4 5 
Line1 : 1 2 3 4 5 
Line1 : 1 2 3 4 5 
Line1 : 1 2 3 4 5 
0

어느 쪽이든 'EE '=> 5,'FF '=> 6);

open F2, "t1.txt";
open F3, "> out.TXT ";
동안() {
      내 $ str을 = $ ,
      인쇄 F3는 ''조인,지도 {S/$
/$의 arr2 {$ }/g; $ } 스플릿//, $ STR;
      인쇄 F3 "\ n ';}

확대 (F2)
폐쇄 (F3);

또는

내 @의 arr1 = ("AA", "BB", "CC", "DD", "EE", "FF");
my % hashArr = map {($ arr1 [$ ] => $ +1}} (0 .. $ # arr1);

open F2, "t1.txt";
open F3, "> out.txt";
while() {
      my $ str = $ ;
      print F3 join '', map {s/$
/$ hashArr {$ }/g; $} 스플릿//, $ str;
      인쇄 F3 "\ n";
}

close (F2);
close (F3);