명령줄의 파일에서 여러 문자열 제거, 고성능 [닫기]

명령줄의 파일에서 여러 문자열 제거, 고성능 [닫기]

입력에서 여러 개의 완전한 문자열을 제거하는 우아하고 성능이 뛰어난 한 줄 방법이 있습니까?

나는 100만 줄 정도의 대용량 텍스트 파일을 다룹니다.입력 파일및 100,000개의 일치하는 문자열히트 파일. Perl 스크립트를 로드했습니다.히트 파일해시에 넣은 다음 각 줄의 모든 "단어"를 확인하세요.입력 파일, 그러나 내 작업 흐름에서는 스크립트보다는 간단한 명령을 선호합니다.

내가 찾고 있는 기능은 다음과 같습니다.

perl -pe 's/\b(string1|string2|string3)\b)//g' 

또는 중첩된 sed를 사용하는 이 접근 방식은 다음과 같습니다.

sed -e "$(sed 's:.*:s/&//ig:' hitfile)" inputfile

또는 셸에서 반복합니다.

while read w; do sed -i "s/$w//ig" hitfile ; done < inputfile

하지만 그건 너무 비싸요. 이 약간 더 효율적인 접근 방식이 효과적입니다(텍스트 파일에서 단어 목록의 모든 항목을 제거하는 방법은 무엇입니까?) 하지만 여전히 느립니다.

perl -Mopen=locale -Mutf8 -lpe '
  BEGIN{open(A,"hitfile"); chomp(@k = <A>)} 
  for $w (@k){s/(^|[ ,.—_;-])\Q$w\E([ ,.—_;-]|$)/$1$2/ig}' inputfile

하지만 이 작업을 더 간결하게 수행할 수 있는 다른 트릭이 있습니까? 제가 간과하고 있는 다른 Unix 명령이나 방법이 있습니까? 정규식은 필요하지 않습니다. 순수/정확한 문자열을 해시(속도를 위해)와 비교하면 됩니다. 즉, "pine"은 "pineapple"과 일치하면 안 되지만 "(pine)"과 일치해야 합니다.

예를 들어, 제가 가진 아이디어 중 하나는 파일의 단어를 별도의 줄로 확장하는 것이었습니다.

앞으로:

Hello, world!

뒤쪽에:


Hello
, 
world
!

그런 다음 grep -vf를 사용하여 행을 처리하고 다시 작성/연결합니다.

다른 빠르고 쉬운 아이디어는 없나요?

답변1

당신의 것은 정확히 얼마나 큽니까 hitfile? 당신이 하려는 일에 대한 몇 가지 실제적인 예를 보여줄 수 있습니까? 입력 데이터에 대한 자세한 내용을 제공하지 않았으므로 이는 다음과 같습니다.그냥 생각시도하고실제 데이터에 대한 벤치마크.

Perl 정규식은 상당히 커질 수 있으며 단일 정규식을 사용하면 입력 파일을 한 번에 수정할 수 있습니다. 여기서는 /usr/share/dict/words거대한 정규식을 작성하는 예로 사용하고 있습니다. 정규식에는 약 99,000개 라인이 있고 크기는 약 1MB입니다.

use warnings;
use strict;
use open qw/:std :encoding(UTF-8)/;

my ($big_regex) = do {
    open my $wfh, '<', '/usr/share/dict/words' or die $!;
    chomp( my @words = <$wfh> );
    map { qr/\b(?:$_)\b/ } join '|', map {quotemeta}
        sort { length $b <=> length $a or $a cmp $b } @words };

while (<>) {
    s/$big_regex//g;
    print;
}

정규식은 필요하지 않습니다. 순수/정확한 문자열을 해시(속도를 위해)와 비교하면 됩니다. 즉, "pine"은 "pineapple"과 일치하면 안 되고 "(pine)"과 일치해야 합니다.

"pine"이 "pineapple"과 일치하면 안 되는 경우 입력에서 "pine"이 나타나는 전후의 문자도 확인해야 합니다. 고정 문자열 접근 방식을 사용하는 것은 확실히 가능하지만 단어 경계에 대한 정규식 개념처럼 들립니다(\b) 당신이 추구하는 것입니다.

우아하고 성능이 뛰어난 한 줄짜리 방법이 있습니까? 내 작업 흐름에서는 스크립트보다 간단한 명령을 선호합니다.

나는 그 감정에 동의하는지 잘 모르겠습니다. 질문이 있으신가요 perl script.pl? 한 줄의 코드처럼 셸 리디렉션/파이핑과 함께 사용할 수 있습니다. 코드를 스크립트에 넣으면 명령줄이 정리되고 모든 것을 한 줄의 코드에 집어넣지 않고도 복잡한 작업을 수행할 수 있습니다. 또한 짧다고 해서 반드시 빠른 것은 아닙니다.

스크립트를 사용하려는 또 다른 이유는 입력 파일이 여러 개 있는 경우입니다. 위에 표시된 코드를 사용하면 정규식을 작성하는 데 비용이 많이 들기 때문에 스크립트를 여러 번 호출하는 데 비용이 많이 듭니다. 단일 스크립트에서 여러 파일을 처리하면 해당 오버헤드가 제거됩니다. 나는 UNIX 원칙을 좋아하지만 빅 데이터의 경우 여러 프로세스를 호출하고(때로는 여러 번) 프로세스 간에 데이터를 파이핑하는 것이 항상 가장 효율적인 접근 방식은 아니며 단일 프로그램에서 모든 것을 단순화하는 것이 도움이 될 수 있습니다.


고쳐 쓰다: 댓글에 따르면, 밧줄은 자신의 발을 쏠 만큼 충분합니다.

관련 정보