2017-09-17 4 views
0

Perl을 사용하여 파일의 내용을 수정하려고합니다.단일 파일 핸들을 사용하여 파일의 내용을 수정하는 방법

다음 스크립트는 정상적으로 작동합니다.

#!/usr/bin/perl 

use strict; 
use warnings; 

open(FH,"test.txt") || die "not able to open test.txt $!"; 
open(FH2,">","test_new.txt")|| die "not able to opne test_new.txt $!"; 

while(my $line = <FH>) 
{ 
     $line =~ s/perl/python/i; 
     print FH2 $line; 
} 
close(FH); 
close(FH2); 

test.txt의 내용 :

im learning perl 
im in File handlers chapter 

test_new.txt의 출력 :

im learning python 
im in File handlers chapter 

내가 파일의 내용을 수정하기위한 동일한 파일 핸들을 사용하려고하면, 난 기대되는 결과를 얻지 못한다. 다음은이 작업을 수행하려고 시도 스크립트 :

#!/usr/bin/perl 

use strict; 
use warnings; 

open(FH,"+<","test.txt") || die "not able to open test.txt $!"; 

while(my $line = <FH>) 
{ 
     $line =~ s/perl/python/i; 
     print FH $line; 
} 
close(FH); 
test.txt에서

잘못된 출력 :

im learning perl 
im learning python 
chapter 
chapter 

가 어떻게 하나의 파일 핸들을 사용하여 파일의 내용을 수정하는 방법은 무엇입니까? Сухой27 @으로

+2

실제로는 다른 파일에 쓰기를 원할 것입니다.'perl -i -pe 's/perl/python/i'test.txt'도 그런 방식으로 작동합니다. 또는 한 번에 전체 파일을 읽고 변경 한 다음 전체 파일을 동일한 핸들에 다시 쓸 수 있습니다. –

+0

@ Сухой27 명령에서 옵션의 기능을 설명 할 수 있습니까? 즉, -i -pe – kart1657

+1

핸들러가 아닌 파일 ** 핸들 **입니다. – melpomene

답변

0

는 유쾌히 사용 onliner 펄 일반적인 상황이다

대답했다.

펄 -i -pe의/펄/파이썬/i '를

perl 옵션

아래
  • -p한다 : 모든 라인이 $_로 지정 선 루프 (기준 라인을 만들어 평가 후 인쇄 $_)
  • -e : 위의 루프에서 코드 블록을 평가하십시오 (기본 피연산자로 $_ 걸림)
  • -i : 당신이 스크립트 아래로 실행하면

(당신이 -i에 대한 인수를 전달하는 경우, 펄이 확장자를 가진 원본 파일을 보존) plcae 파일 편집에

펄 -i.bak -pe '가 S/펄/파이썬/난 당신이 수정 얻을 것이다

TEST.TXT test.txt

im learning python 
im in File handlers chapter 

얻을 원본 텍스트 파일 (끝 제외) test.txt.bak

im learning perl 
im in File handlers chapter 
+1

두 핸들을 사용합니다. – ikegami

2

당신은 파일에서 삭제할 수 없습니다에 이름.
파일에 문자를 삽입 할 수 없습니다 (끝 부분 제외).

파일의 문자를 바꿀 수 있습니다.
파일에 추가 할 수 있습니다.
파일을 축소 할 수 있습니다.
그게 전부입니다.

파일에서 "Perl"을 "Python"으로 간단하게 바꿀 수 있다고 상상할 수 있습니다. 그것들은 같은 길이가 아니기 때문에 파일에 문자를 삽입해야하며 그렇게 할 수 없습니다.

파일의 나머지 부분을 메모리에로드하고 두 문자를 다시 쓰면 효과적으로 파일에 문자를 삽입 할 수 있습니다. 그러나 이렇게하면 매우 큰 파일에 대해 까다로워집니다. 또한 문자를 삽입 할 때마다 파일의 (아마도 매우 큰) 부분을 복사하기 때문에 매우 느립니다.

내부 수정의 다른 문제는 오류를 복구 할 수 없다는 것입니다. 문제가 발생하면 불완전하거나 손상된 파일이 남아있게됩니다.

파일이 작고 잘못되었을 때 데이터를 잃어 버리는 경우 가장 간단한 방법은 전체 파일을 메모리에로드하는 것입니다.

open(my $fh, '<+', $qfn) 
    or die("Can't open \"$qfn\": $!\n"); 

my $file = do { local $/; <$fh> }; 

$file =~ s/Perl/Python/g; 

seek($fh, 0, SEEK_SET) 
    or die $!; 
print($fh $file) 
    or die $!; 
truncate($fh) 
    or die $!; 

더 안전한 방법은 데이터를 새 파일에 쓰고 완료되면 파일의 이름을 바꾸는 것입니다.

my $new_qfn = $qfn . ".tmp"; 
open(my $fh_in, '<', $qfn) 
    or die("Can't open \"$qfn\": $!\n"); 
open(my $fh_out, '<', $new_qfn) 
    or die("Can't create \"$new_qfn\": $!\n"); 

while (<$fh_in>) { 
    s/Perl/Python/g; 
    print($fh_out $_); 
} 

close($fh_in); 
close($fh_out); 

rename($qfn_new, $qfn) 
    or die $!; 

이 접근법의 단점은 파일의 사용 권한이 변경 될 수 있으며 하드 링크가 새 파일 대신 이전 내용을 가리키게된다는 것입니다. 또한 파일을 만들 수있는 권한이 필요합니다.