줄 번호로 파일 필터링


17

줄당 하나의 음수가 아닌 정수를 가진 파일 L과 텍스트 파일 F가 주어지면 줄 번호가 파일 L에 나타나는 F의 줄만 유지하는 가장 빠른 방법은 무엇입니까?

예:

$ cat L.txt
1
3

$ cat F.txt
Hello World
Hallo Welt
Hola mundo

$ command-in-question -x L.txt F.txt
Hello World
Hola mundo

5 억 개 이상의 항목이있는 파일 L을 처리 할 수있는 명령을 찾고 있습니다. 파일 L은 숫자로 정렬됩니다.

참고 : 구현을 반쯤 진행 command-in-question했지만 여기에서 유닉스 도구를 사용할 수 있는지 궁금합니다.


업데이트 : 모든 답변에 감사드립니다. 오늘 많은 것을 배웠습니다! 하나 이상의 답변을 수락하고 싶지만 불가능합니다.


파일 F에 몇 줄이 있습니까?
Peter.O

1
L 에서처럼 F에는 최소한 많은 줄이 있습니다.
miku

답변:


8

C의미있는 오류 메시지를 생략 하면 :

#include <stdio.h>
#include <stdlib.h>

int main (int argc, char *argv[]) {

    FILE *L;
    FILE *F;

    unsigned int to_print;
    unsigned int current = 0;
    char *line = NULL;
    size_t len = 0;

    if ((L = fopen(argv[1], "r")) == NULL) {
        return 1;
    } else if ((F = fopen(argv[2], "r")) == NULL) {
        fclose(L);
        return 1;
    } else {

        while (fscanf(L, "%u", &to_print) > 0) {
            while (getline(&line, &len, F) != -1 && ++current != to_print);
            if (current == to_print) {
                printf("%s", line);
            }
        }

        free(line);
        fclose(L);
        fclose(F);
        return 0;
    }
}

2
이것이 가장 성능이 좋은 답변입니다. 적어도 내 테스트에 의한 것입니다. 관심있는 사람이 있다면 다음과 같이 컴파일했습니다 xsel -bo | cc -xc - -o cselect. 그리고 그것은 방금 작동했습니다-두 개의 라이브러리 만 필요합니다.
mikeserv 2016 년

1
고마워요, 대단합니다! 마음에 들지 않기를 희망하지만 코드를 작은 도구 로 묶었습니다 .
miku

1
@miku 계속해서 도와 드리겠습니다. LINE_MAX버전 이 증가한 것으로 나타 났으 므로 파일에서 매우 큰 줄로 작업 할 수 있습니다. getline()라인 크기 제한을 제거하는 데 사용하는 버전으로 A를 업데이트했습니다 .
FloHimself 2016 년

@FloHimself, 다시 한번 감사드립니다 :) 실제로 일부 입력 줄이를 ​​초과 할 수 LINE_MAX있으므로 getline올바르게 보입니다.
miku

10

사용 awk하지만 L.txt메모리 의 전체 내용을 저장하지 않고 불필요한 해시 조회를 수행합니다. ;-).

list=L.txt file=F.txt
LIST="$list" awk '
  function nextline() {
    if ((getline n < list) <=0) exit
  }
  BEGIN{
    list = ENVIRON["LIST"]
    nextline()
  }
  NR == n {
    print
    nextline()
  }' < "$file"

정확히, 나는 해시 맵을 시도했는데 메모리를 초과합니다. 비트 세트는 더 많은 헤드 룸을 구매할 것입니다. 그러나 입력을 정렬한다는 사실을 사용하면이 (공간) 문제를 완전히 제거 할 수 있습니다.
miku

1
@ 재니; 표준 코딩에 대한 좋은 사례는 아닙니다. 리터럴을 하드 코딩하지 말고 대신 변수를 사용하십시오. (보다 유연하고 오류가 적고 유지 관리가 쉬워집니다)
Peter.O

1
@ StéphaneChazelas : 그것은 사전 루프 초기화가 필요합니다 n(있는 그대로) 그렇지 않으면 그리워 1L.txt
Peter.O

1
@ Peter.O, 죄송합니다. NR> = n으로 해결하려고 시도했지만 잘못되었습니다. 지금 나아 져야합니다.
Stéphane Chazelas 2016 년

1
@Janis, 아이디어는 해당 코드가 command-in-question스크립트에 포함 되면 파일 이름 을 코드에 포함 시킬 수 없다는 것입니다. -v list="$opt_x"백 슬래시 처리 때문에 awk로 인해 작동하지 않습니다. 그래서 여기서 대신 ENVIRON을 사용합니다.
Stéphane Chazelas 2016 년

10

grep -n | sort | sed | cut

(   export LC_ALL=C
    grep -n ''   | sort -t:  -nmk1,1 ./L - |
    sed /:/d\;n  | cut  -sd: -f2-
)   <./F

그것은 모든 크기의 입력으로 꽤 빨리 작동합니다 (일부 시간 테스트가 아래에 포함되어 있음) . 방법에 대한 몇 가지 참고 사항 :

  • export LC_ALL=C
    • 다음 작업의 요점은 전체 파일을 lineno의 파일 ./F과 인라인으로 쌓는 ./L것이므로 ASCII [0-9]문자와 :콜론 만 걱정할 필요가 있습니다 .
    • 따라서 UTF-8이 포함 된 경우보다 128 개 문자 집합에서 11 개의 문자를 찾는 것에 대해 걱정하는 것이 더 간단합니다.
  • grep -n ''
    • 그러면 LINENO:stdin-또는에서 모든 줄의 머리글에 문자열이 삽입됩니다 <./F.
  • sort -t: -nmk1,1 ./L -
    • sort무시 전혀 입력 파일을 정렬하고 대신합니다 (제대로) 가 미리 정렬되어 가정 및 -m그들을 erges -numerically기본적으로 가능한 모든 이외에는 아무 것도 무시하고, 정렬 된 순서 -k1,1일 발생 -t:어쨌든 콜론 문자를.
    • 이것은 (일부 시퀀스가 ​​얼마나 멀리 떨어져 있는지에 따라) 수행 할 임시 공간이 필요할 수 있지만 적절한 정렬과 비교할 때 많이 필요하지 않으며 백 트랙킹이 없기 때문에 매우 빠릅니다.
    • sort./L라인 번호가의 해당 라인 바로 앞에 오는 단일 스트림을 출력합니다 ./F. ./L줄이 항상 짧기 때문에 항상 줄이 먼저 나옵니다.
  • sed /:/d\;n
    • 현재 행이 /:/콜론 과 일치하면 d출력에서 제외됩니다. 그렇지 않으면 현재 및 n내선을 자동 인쇄합니다 .
    • 그리고 sed자두 sort에의 출력 만을 콜론과 다음 줄을 일치하지 않는 연속 라인 쌍 - 또는에서 불과 라인에 ./L다음 다음.
  • cut -sd: -f2-
    • cut -selimiter -d:문자열 중 하나 이상을 포함하지 않는 입력 행의 출력을 억제합니다. 따라서 ./L행이 완전히 제거됩니다.
    • 그런 줄에 대해서는 첫 번째 :콜론으로 구분 된 -f필드가 cut사라지고 grep삽입 된 모든 lineno 가 사라집니다 .

작은 입력 테스트

seq 5 | sed -ne'2,3!w /tmp/L
        s/.*/a-z &\& 0-9/p' >/tmp/F

... 5 줄의 샘플 입력을 생성합니다. 그때...

(   export LC_ALL=C; </tmp/F \
    grep -n ''   | sort -t:  -nmk1,1 ./L - |
    sed /:/d\;n  | cut  -sd: -f2-
)|  head - /tmp[FL]

...인쇄물...

==> standard input <==
a-z 1& 0-9
a-z 4& 0-9
a-z 5& 0-9

==> /tmp/F <==
a-z 1& 0-9
a-z 2& 0-9
a-z 3& 0-9
a-z 4& 0-9
a-z 5& 0-9

==> /tmp/L <==
1
4
5

더 큰 시한 테스트

꽤 큰 파일 몇 개를 만들었습니다.

seq 5000000 | tee /tmp/F |
sort -R | head -n1500000 |
sort -n >/tmp/L

... /tmp/F5mil 라인을 넣고 1.5mil을 임의로 선택한 라인에 넣습니다 /tmp/L. 나는 그랬다.

time \
(   export LC_ALL=C
    grep -n ''   | sort -t:  -nmk1,1 ./L - |
    sed /:/d\;n  | cut  -sd: -f2-
)   <./F |wc - l

인쇄 :

1500000
grep -n '' \
    0.82s user 0.05s system 73% cpu 1.185 total
sort -t: -nmk1,1 /tmp/L - \
    0.92s user 0.11s system 86% cpu 1.185 total
sed /:/d\;n \
    1.02s user 0.14s system 98% cpu 1.185 total
cut -sd: -f2- \
    0.79s user 0.17s system 80% cpu 1.184 total
wc -l \
    0.05s user 0.07s system 10% cpu 1.183 total

(백 슬래시를 추가했습니다)

현재 여기에 제공되는 솔루션 중에서 이것은 가장 빠르지 만 내 컴퓨터에서 위에서 생성 된 데이터 세트에 대해 피트했을 때 하나입니다. 다른 사람들 중 단 한 사람 만이 2 위를 차지하기 시작 perl 했습니다 .

이것은 원래 제공된 솔루션이 결코 아닙니다. 다른 사람들이 제공하는 조언 / 영감 덕분에 실행 시간의 3 분의 1이 줄었습니다. 더 느린 솔루션에 대해서는 포스트 히스토리를 참조하십시오 (그러나 그 이유는 무엇입니까?) .

또한 내 시스템의 다중 CPU 아키텍처가 아니고 해당 파이프 라인의 각 프로세스를 동시에 실행하지 않으면 다른 답변이 훨씬 더 잘 경쟁 할 수 있습니다. 이들은 모두 동시에 자체 프로세서 코어에서 데이터를 전달하고 전체의 작은 부분을 수행하면서 동시에 작동합니다. 꽤 멋지다.

그러나 가장 빠른 해결책은 ...

그러나 가장 빠른 솔루션은 아닙니다. 여기서 제공되는 가장 빠른 솔루션은 C 프로그램 입니다. 나는 그것을 불렀다 cselect. X 클립 보드에 복사 한 후 다음과 같이 컴파일했습니다.

xsel -bo | cc -xc - -o cselect

나는 그랬다.

time \
    ./cselect /tmp/L /tmp/F |
wc -l

... 결과는 ...

1500000
./cselect /tmp/L /tmp/F  \
    0.50s user 0.05s system 99% cpu 0.551 total
wc -l \
    0.05s user 0.05s system 19% cpu 0.551 total

1
sed -ne'/:/!{n;p;}' | cut -d: -f2-sed -ne'/:/!N;/\n/s/[^:]*://p'
Stéphane Chazelas

@ StéphaneChazelas- seds 를 전환하면 더 나은 결과를 얻을 수 있습니다 - sed사용중인 가보입니다 sed- 결과 에서 alias값을 볼 수 있습니다 time. 그런데 내 가보 패키지는 TRE를 기반으로 하는 정규식 구현 인 musl libc에 대해 정적으로 컴파일 됩니다. GNU로 전환 sed하고 실행하지 않고 cut완료 시간 (2.8 초)에 1 초 를 더 추가하면 3 분의 1 이상이됩니다. 그리고 그것은 내 시스템에서 당신보다 0.3 초 ​​빠릅니다.
mikeserv 2016 년

1
sort -mn반대로 sort -nmk1,1당신이 여기 (테스트하지) 분할을 할 필요가 없기 때문에 더 좋을 수도
스테판 Chazelas가

@ StéphaneChazelas-예, 나는 똑같이 생각하고 모든 방법으로 시도했습니다. -n내가 좋아, 생각 있도록 행의 첫 번째 숫자 문자열을 그냥 spec'd한다 -mn또는 -nm내가 같이 모든 옵션에 추가 할 때였다 어떤 이유로 만 번 이제까지 완료 시간 2 초 이하로 감소합니다. 그것은 이상합니다-어제 -m처음부터 고정하지 않은 이유입니다. 제가 무엇에 관한 것인지 알았지 만 일종의 자동 최적화로 작동하는 것처럼 보였습니다. 흥미롭게도, 가보 sort에는 -z문자열 길이 옵션 만 있습니다 -[cm]. ....
mikeserv

-n줄의 첫 번째 숫자 문자열 이 아닙니다 . 이 숫자는 행을 숫자로 간주하므로 abc 1230이됩니다. 따라서 다음 보다 효율성이 떨어질 수 없습니다.-t: -k1,1
Stéphane Chazelas

9

나는 사용할 것이다 awk:

awk 'NR==FNR {a[$1]; next}; FNR in a' L.txt F.txt

업데이트 : 성능 측정을 마쳤습니다. 비교가 매우 빠르며 해시 테이블을 작성하는 데 필요한 노력을 과도하게 보상하기 때문에이 버전은 매우 큰 데이터 세트 (규정 된 요구 사항의 경우와 같이)를 사용하여 확장하는 것이 더 좋습니다.


1
@ 미쿠; 예, 멋진 컴팩트 솔루션입니다. 그러나주의 사항; 모든 사람이 awk그러한 거대한 데이터 세트를 처리 할 수있는 것은 아닙니다 . -저는 GNU를 사용 awk하고 있으며 아무런 문제가 없습니다. 5 억 줄의 데이터 테스트에는 7 분이 소요되었습니다.
Janis

1
(비교하여)이 다소 느린 real 16m3.468s- user 15m48.447s- sys 0m10.725s. 그것은 1 / 10'th 크기 테스트 RAM의 3.3 GB의 사용 L50,000,000 라인; 과 F500,000,000 라인 - 스테판 Chazelas가 'AWK의 답변 시간 : real 2m11.637s- user 2m2.748s- sys 0m6.424s- 나는 빠른 상자를 사용하지 않는,하지만 비교가 흥미 롭다.
Peter.O

@ 피터 .O; 데이터 주셔서 감사합니다! (내 자신의 테스트 사례에서) 50 억 라인 이 연관 배열에 저장 되었다는 점을 감안하면 속도가 느려질 것으로 예상 되었다. (그래서 내가 Stephane의 제안에 대해 위의 "(+1)"을 언급 한 이유입니다.)-이 간결한 솔루션이 여전히 초당 100 만 라인을 처리하고 있다는 사실에 놀랐습니다! 이 코드 패턴 (단순하기 때문에!)을 실행 가능한 옵션으로 만들고 특히 데이터 크기가 적은 경우에 적합하다고 생각합니다.
Janis

확실히 실행 가능한 솔루션입니다. 테스트 데이터에서 (5mil 라인 / 1.5mil L) 4 초 조금만에 완료했습니다 -Stephane 의 답변보다 1 초 뒤에 완료되었습니다. 테스트 세트를 생성하는 데 사용되는 코드는 내 대답에 있지만 대부분 seq출력이며 L 에서 동일한 무작위로 선택된 작은 하위 집합입니다 .
mikeserv

1
방금 5 억 줄의 데이터 파일 크기와 5 천만 키의 키 파일 크기로 더 많은 성능 측정을 수행했습니다. 주목할만한 관찰과 함께 5 억 라인. 키 파일이 작을수록 시간은 4 분 (Stephane) 대 8 분 (Janis)이고 키 파일이 클수록 19 분 (Stephane) 대 12 분 (Janis)입니다.
Janis

3

완전성을 위해 : 우리는 Stéphane Chazelas의 대답에 우수한 awk 스크립트와 kos의 대답에있는 perl 스크립트를 병합 할 수 있지만 perl이 awk보다 빠를 수 있기를 바랍니다. (원래 질문과 일치하도록 인수 순서를 변경했습니다).

#!/usr/bin/env perl
use strict;

die "Usage: $0 l f\n" if $#ARGV+1 != 2;
open(L,$ARGV[0]) or die "$ARGV[0]: $!";
open(F,$ARGV[1]) or die "$ARGV[1]: $!";

while(my $number = <L>){
    #chop $number;
    while (<F>) {
        if($. == $number){
            print;
            last;
        }
    }
}

이보다 빠릅니다 awk. 내 속도만큼이나 빠릅니다. 지금 막 세 번 테스트를했는데 매번 1.8 밀리 초와 1 초마다 1.9 ... 초 만에 5mil 라인 테스트 세트를 처리했습니다. 관심이 있다면 테스트 세트 gen 코드가 내 대답에 있지만 요점은 매우 좋습니다. 더구나, 결과는 정확 awk합니다. 여전히 작업을 수행 할 수 없습니다 ... 그럼에도 불구하고 FloHimself 's에 의해 우리의 답이 부끄러워졌습니다 .
mikeserv

@ mikeserv, 우리는 다른 awks 를 가져야합니다 . 샘플에서 gawk (Janis의 경우 4s), mawk의 경우 0.9s,이 perl 솔루션의 경우 1.7s, kos '의 경우 2.3s, Gss의 경우 4.5s (GNU sed)의 경우 1.4s, GNU sed)와 내가 제안한 개선 사항 (C 솔루션의 경우 0.5s).
Stéphane Chazelas 2016 년

@ mikeserv, 아! 물론 접근 방식에 따라 로케일이 달라집니다. 여기 2.3s에 4.5 초 초과에서 내려 C.에 UFT-8에서 전환 할 때
스테판 Chazelas가

3

간단한 Perl 스크립트를 작성했습니다.

Usage: script.pl inputfile_f inputfile_f

#!/usr/bin/env perl

$number_arguments = $#ARGV + 1;
if ($number_arguments != 2) {
    die "Usage: script.pl inputfile_f inputfile_l\n";
}

open($f, '<', $ARGV[0])
    or die "$ARGV[0]: Not found\n";
open($l, '<', $ARGV[1])
    or die "$ARGV[1]: Not found\n";

@line_numbers = <$l>;

while ($line = <$f>) {
    $count_f ++;
    if ($count_f == @line_numbers[$count_l]) {
        print $line;
        $count_l ++;
    }
}
  • 잔뜩 F.txt
  • 잔뜩 L.txt
  • 각 줄을 L.txt배열에 저장
  • F.txt현재 줄 번호와 현재 배열 색인을 추적하여 한 줄씩 읽 습니다. F.txt현재 줄 번호를 증가시킵니다 . 경우 생성 F.txt전류 선 번호가 현재 배열 인덱스에 어레이의 내용과 일치하는, 상기 전류 선을 인쇄하고 인덱스를 증가

비용 및 복잡성 고려 사항 :

할당 비용, 비교 비용 및 라인 인쇄 비용을 고려하여 N 1 을 라인 수로 F.txt, N 2 를 라인 수로 지정 L.txt하면 while루프는 최대 N 1 번 실행됩니다 . 2N 1 + N 2 할당 (명명하게 N 1 > N 2로 가정 ), 2N 1 비교 및 N 2 프린트로 이어짐; 각 작업의 비용이 동일 할 경우 while루프 를 실행하는 데 드는 총 비용 은 4N 1 + 2N 2 이므로 O (N) 스크립트가 복잡해집니다.

1000 만 줄의 입력 파일에서 테스트하십시오 .

10 만 라인을 사용하여 F.txt무작위로 50 자 길이의 라인을 포함하는 파일과 10 만 라인의 L.txt10000000-1에서 번호가 들어있는 파일 (최악의 시나리오) :

~/tmp$ for ((i=0; i<3; i++)); do time ./script.pl F.txt L.txt > output; done

real    0m15.628s
user    0m13.396s
sys 0m2.180s

real    0m16.001s
user    0m13.376s
sys 0m2.436s

real    0m16.153s
user    0m13.564s
sys 0m2.304s

2

이 perl 솔루션은 다른 awk 또는 perl 솔루션보다 20 % 정도 빠르지 만 C의 솔루션만큼 빠르지는 않습니다.

perl -e '
  open L, shift or die $!;
  open F, shift or die $!;
  exit if ! ($n = <L>);
  while (1) {
    $_ = <F>;
    next if $. != $n;
    print;
    exit if ! ($n = <L>);
  }
' -- L F

0
cat <<! >L.txt
1
3
!

cat <<! >F.txt
Hello World
Hallo Welt
Hola mundo
!

cmd(){
 L=$1 F=$2
 cat -n $F |
 join $L - |
 sed 's/[^ ]* //'
}

cmd L.txt F.txt
Hello World
Hola mundo

L.txt가 정렬되어 있으므로 join을 사용할 수 있습니다. F.txt의 각 줄에 번호를 매기고 두 파일을 결합한 다음 줄 번호를 제거하십시오. 큰 중간 파일이 필요하지 않습니다.

실제로 위의 모든 공백을 단일 공백으로 바꾸어 데이터 라인을 혼란스럽게합니다. 줄을 그대로 유지하려면 데이터에 나타나지 않는 문자 (예 : "|")를 구분 기호로 선택해야합니다. 그러면 cmd는

cmd(){
 L=$1 F=$2
 cat -n $F |
 sed 's/^ *//;s/\t/|/' |
 join -t'|' $L - |
 sed 's/[^|]*|//'
}

첫 번째 sed는 "cat -n"출력에서 선행 공백을 제거하고 탭을 대체합니다. 두 번째 sed는 줄 번호와 "|"를 제거합니다.


더 큰 파일에서는 이것이 작동하지 않을까 걱정됩니다. <10 줄이 필요합니다. 나는 같은 생각을 가지고 시도 join L.txt <(nl F.txt )했지만 큰 파일에서는 작동하지 않습니다. 그런데 사이트에 오신 것을 환영합니다. 새로운 사용자로부터 명확하고 형식이 지정된 답변을받는 것은 아닙니다.
terdon

@terdon, 예, 부끄러운 그 join/ comm숫자 분류 입력하지 작업 할 수 있습니다.
Stéphane Chazelas 2016 년

@ terdon : 나는 당신의 리드를 따라 갔고 (지금 삭제되었습니다) 시도했습니다 join -t' ' <(<L.txt awk '{printf("%010s\n",$0)}') <(<F.txt awk '{printf("%010s %s\n",NR,$0)}') | cut -d' ' -f2--느 렸습니다! -적절한 0 패딩 키가있는 준비된 파일을 넣었을 때도 join -t' ' L.txt F.txt | cut -d' ' -f2- 여전히 느립니다 (준비 시간 제외)-@ awkJanis 의 답변 보다 느립니다 (여기에서 실제 시간을 모두 기록 한 곳에서 의견을 게시했습니다) 그의 @ StéphaneChazelas '답변
Peter.O

@ Peter.O 그래. 나는 awks 중 하나를 피하는 비슷한 접근법시도했지만 그것이 효과가 있고 가치가있는 방법을 찾지 못했습니다.
terdon

@terdon 등 다음의 실제 시간 join+의 awk printf 프로세스 substiturion가 있었다 real 20m11.663s user 19m35.093s sys 0m10.513s 스테판 Chazelas가 '대 real 2m11.637s user 2m2.748s sys 0m6.424s 사용하여 L5000 만 개 라인, F5 억 명 선.
Peter.O

0

완전성을 위해 join솔루션 에 대한 또 다른 시도 :

sed -r 's/^/00000000000000/;s/[0-9]*([0-9]{15})/\1/' /tmp/L | join <( nl -w15 -nrz /tmp/F ) - | cut -d' ' -f2-

이것은 결합하는 행 번호 열의 형식을 지정하여 앞에 오는 0을 사용하여 고정 길이로 작동하므로 숫자의 길이는 항상 15 자리입니다. 열이 효과적으로 사전 정렬이되었으므로 일반적인 숫자 정렬 순서를 좋아하지 않는 조인 문제를 피할 수 있습니다. nl이 형식의 줄 번호를 F.txt에 추가하는 데 사용됩니다. 불행히도 sedL.txt의 번호 매기기 형식을 다시 지정해야합니다.

이 접근법은 @mikeserv의 방법을 사용하여 생성 된 테스트 데이터에서 제대로 작동하는 것 같습니다. 그러나 여전히 매우 느립니다-c 솔루션은 내 컴퓨터에서 60 배 빠릅니다. 시간의 약 2/3는 sed1/3에서 소비 됩니다 join. 아마도 더 나은 sed 표현이있을 것입니다 ...


좋아-그러나 왜 우리는 모든 0을 앞에 두는가? 이 느낌을 얻으려고합니다. 또한,nl 매우 멋지지만 테스트되지 않은 입력에는 강력하게 사용할 수 없습니다. 그것을 멋지게 만드는 것 중 하나는 논리적 페이지 이미 터 -d 입니다. 기본적으로 단지 문자열로 구성된 입력의 모든 라인이있는 경우 :\` (단, W / 후행 무덤에서) 연속 1, 2, 3 또는 세 번, 당신의 수는 조금 미친 갈 것입니다. 그것으로 실험-그것은 꽤 깔끔합니다. 특히 nl`가 1 개의 구분자 문자열이있는 줄을 읽은 다음 나중에 3 또는 2가있는 줄을 읽을 때 어떤 일이 발생하는지 살펴보십시오
mikeserv

0

허용 된 답변이 C에 있기 때문에 파이썬 솔루션을 여기에 넣는 것이 좋습니다.

# Read mask
with open('L.txt', 'r') as f:
    mask = [int(line_num) for line_num in f.read().splitlines()]

# Filter input file
filtered_lines = []
with open('F.txt', 'r') as f:
    for i, line in enumerate(f.read().splitlines()):
        if (i+1) in mask:
            filtered_lines.append(line)

# Write newly filtered file
with open('F_filtered.txt', 'w') as f:
    for line in filtered_lines:
        f.write('%s\n' % line)

numpy와 같은 외부 라이브러리를 사용하는 경우 솔루션이 더욱 우아해 보입니다.

import numpy as np

with open('L.txt', 'r') as f:
    mask = np.array([int(line_num)-1 for line_num in f.read().splitlines()])

with open('F.txt', 'r') as f:
    lines = np.array(f.read().splitlines())
filtered_lines = lines[mask]

with open('F_filtered.txt', 'w') as f:
    for line in filtered_lines:
        f.write('%s\n' % line)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.