2012-08-26 2 views
0

정렬 된 형식의 데이터가있는 perl의 텍스트 파일에 줄을 추가하고 싶습니다. 필자는 파일 끝에 데이터를 추가하는 방법을 보여주는 예제를 보았습니다. 그러나 데이터를 정렬 된 형식으로 원하기 때문에.Perl : 정렬 된 텍스트 파일에 줄을 추가하는 방법

어떻게 안내해주십시오.

기본적으로 지금까지 시도한 내용 : (파일을 열어 grep의 내용을보고 파일에 이미 추가하고 싶은 줄이 있는지 확인합니다. 끝내기 만하면 파일에 추가됩니다. 어쨌든 텍스트 파일의 내용을 읽을 가지고 있기 때문에, 다른 접근 방법에 대해?

하면 파일의 라인을 읽기 방법

open(my $FH, $file) or die "Failed to open file $file \n"; 
@file_data = <$FH>; 
close($FH); 
my $line = grep (/$string1/, @file_data); 
if($line) { 
    print "Found\n"; 
    exit(1); 
} 
else 
{ 
    #add the line to the file 
    print "Not found!\n"; 
} 
+0

는 [이]보고 [1] [1] : http://stackoverflow.com/questions/12070115/reading-and-writing-to-an-existing -file-in-perl – Vijay

답변

1

(데이터 정렬 형식으로 같은 유지) 하나의 별 목표 문자열과 비교하여 한 줄을 읽으면 아무 것도 할 필요가 없습니다.

그렇지 않으면 결국 정렬 기준에 따라 현재 행보다 큰 행을 읽거나 파일 끝에 도달하게됩니다. 전자의 경우에는 해당 위치에 문자열을 삽입 한 다음 나머지 줄을 복사하면됩니다. 후자의 경우 문자열을 끝에 추가하십시오.

그런 식으로하고 싶지 않은 경우 @file_data에서 이진 검색을 수행하여 모든 항목을 검사하지 않고 그 행을 추가 한 다음 해당 항목을 배열에 삽입하여 출력 할 수 있습니다 배열을 파일에 추가하십시오.

2

파일을 배열로 쉽게 처리 할 수 ​​있도록 Tie::File을 사용하는 접근 방식이 있습니다. List::BinarySearchbsearch_str_pos 기능을 사용하면 신속하게 삽입 지점을 찾을 수 있습니다. 삽입 점을 찾으면 해당 점의 요소가 삽입 문자열과 같은지 확인합니다. 그렇지 않은 경우 splice 배열에 넣습니다. 동일하면 끼워 넣지 말고 untie으로 마무리하면 파일이 완전히 닫힙니다. List::BinarySearch에서

use strict; 
use warnings; 
use Tie::File; 
use List::BinarySearch qw(bsearch_str_pos); 

my $insert_string = 'Whatever!'; 
my $file   = 'something.txt'; 

my @array; 
tie @array, 'Tie::File', $file or die $!; 

my $idx = bsearch_str_pos $insert_string, @array; 

splice @array, $idx, 0, $insert_string 
    if $array[$idx] ne $insert_string; 

untie @array; 

bsearch_str_pos 함수 Mastering Algorithms with Perl에서 이진 검색 구현의 적응이다. 편리한 특성은 검색 문자열을 찾을 수없는 경우 정렬 순서를 유지하면서 삽입 할 수있는 인덱스 지점을 반환한다는 것입니다.

+0

Mr O! 훌륭한 라이브러리를 ginormous 파일에 사용하도록 알려 주셔서 감사합니다. 그러나 한 가지 질문 : b- 검색을 구현하는 것이 거의 불가능한 것처럼 보이는 경우 어떻게하면 올바른지 확인할 수 있습니까? – Chris

+1

바이너리 검색은 정확하게 구현하기가 불가능하지 않습니다. 매우 기본입니다. 그러나 실수가 발생하고 이론 상으로는 소수만 사용하는 일회용 솔루션보다 많은 사람들이 코드를보고 사용하면 더 빨리 발견됩니다. 소스 코드는 공개적으로 사용 가능하며 일반 버그 리포트와 요청을 환영합니다. – DavidO

+0

실제로 내가 엄청나게 (11gigs, 300m 레코드) 파일을 찾고있는 사람들을 위해 (내가 https://haveibeenpwned.com/Passwords를하고 있는지 알고 싶다면 여기를 확인하십시오) 파일 : 넥타이가 실제로 완전히 떨어졌습니다 :(100 % cpu, 지붕을 통한 RAM 사용, 미친 듯이 스와핑. 내 워크 스테이션을 죽이기 전에 죽임. – Chris

0

다음은 stdin (또는 명령 줄에 지정된 파일 이름)에서 읽는 간단한 버전이며 입력에 'string to append'를 추가하면 출력에 추가됩니다. 출력은 표준 출력에 인쇄됩니다. A (펄 -i와) 현재 위치에서 파일 및 명령 줄에서 APPEND 문자열을 복용하는 것은 매우 간단 할 것을 편집을 수정

#! /usr/bin/perl 

$found = 0; 
$append='string to append'; 

while(<>) { 
    $found = 1 if (m/$append/o); 
    print 
} 

print "$append\n" unless ($found);; 

.

0

A '단순한'하나의 라이너가 될 수있는 모듈을 사용하지 않고 라인을 삽입하려면

perl -ni -le '$insert="lemon"; $eq=($insert cmp $_); if ($eq == 0){$found++}elsif($eq==-1 && !$found){print$insert} print' 

주는 그 컨텍스트 인 list.txt :

ananas 
apple 
banana 
pear 

출력은 :

ananas 
apple 
banana 
lemon 
pear 
+0

이것은 가장 좋은 해결책이지만 약간의 가독성과 함께 할 수 있습니다. 실제로 한 줄짜리 일 필요는 없습니다. '$^I' 전역 변수로 내부 편집 모드를 활성화 할 수 있습니다. – hobbs

0
{ 
    local ($^I, @ARGV) = ("", $file); # Enable in-place editing of $file 

    while (<>) { 
    # If we found the line exactly, bail out without printing it twice 
    last if $_ eq $insert; 
    # If we found the place where the line should be, insert it 
    if ($_ gt $insert) { 
     print $insert; 
     print; 
     last; 
    } 
    print; 
    } 
    # We've passed the insertion point, now output the rest of the file 
    print while <>; 
} 

필수 많은 가독성이 추가 된 경우를 제외하고는 pavel과 동일한 대답입니다. $insert에는 이미 줄 바꿈이 있어야합니다. 펄 PLS 올바른 위치에서 편집

관련 문제