텍스트 조작: 정렬된 목록에서 x <= $input 값을 제거하고 일반화합니다.

텍스트 조작: 정렬된 목록에서 x <= $input 값을 제거하고 일반화합니다.

내 입력 텍스트 파일에는 1줄 헤더가 포함되어 있으며 그 뒤에 공백으로 구분된 xy 및 x,y 64비트 정수를 포함하는 정렬된 줄 목록이 있습니다. 입력 파일의 길이는 수백만 줄입니다.

지금 나는 원한다2번째 줄부터 #end#까지 삭제value <= $input으로 시작하는 모든 줄. 이렇게 하면 각 게임의 전체 행이 제거됩니다. 지금까지 나의 우아하지 않은 해결책은 다음과 같습니다.

head -1 inputFile > inputFile2 # 헤더 유지
lineNum=$( grep -n $input test | cut -f1 -d ':' ) # $input과 일치하는 줄 찾기
tail -n +$( $lineNum+1 ) inputFile >> inputFile2 # 값 > $input에 도달할 때까지 아래쪽으로 입력을 건너뜁니다.
rm 입력 파일
mv 입력 파일 2 입력 파일

입력 파일 예

5066314878607:a1:a2:a3:a4:a5
1 27
3 27
7 27
11 27
13 27
17 27
...

[GNU 도구 분할] inputFile은 inputFile-1과 inputFile-2(2개 코어, 가능하면 z 코어)로 나뉩니다.

입력 파일-1:
5066314878607:a1:a2:a3:a4:a5
1 27
7 27
13 27

입력 파일-2
5066314878607:a1:a2:a3:a4:a5
3 27
11 27
17 27

이제 inputFile-1은 '까지 처리되고 완료됩니다.727'. 기본 inputFile에서 다음 두 줄만 포함하고 싶습니다. (분할 inputFile-1의 <=에 유의하세요. 그러나 이는 루프 분할로 인해 원래 inputFile에서 제거된 단순한 <= x가 아닙니다.)

1 27
7 27

그러면 inputFile이 다음과 같이 됩니다.

5066314878607:a1:a2:a3:a4:a5
3 27
11 27
13 27
17 27

현재 Ubuntu 16.04에서 실행되지만 이는 모든 최신 Linux 배포판에서도 동일할 것입니다.

질문:

  • 기존 코드를 개선할 수 있나요?
  • 개별적으로 삭제된 많은 파일을 처리하도록 일반화하려면 어떻게 해야 합니까?

개별적으로 처리된 각 inputFile-x는 순차적으로 처리됩니다. 루프 분할을 통해 기본 파일에서 처리된 줄을 제거하는 방법을 모르겠습니다. 특히, 서로 다른 속도의 많은 컴퓨터에서 실행되므로 inputFile-1은 라인 300으로 처리될 수 있고, inputFile-2는 라인 500으로 처리될 수 있습니다.

각각 별도로 처리되는 z 코어로 일반화하는 방법을 설명합니다. inputFile은 inputFile-1 inputFile-2 inputFile-3 ... inputFile-z로 루프 분할됩니다. [즉, 50개 코어의 경우 분할 -nr/$z: 분할 -nr/50 inputFile]

Core1: inputFile-1(라인 2에서 #end#까지의 값) <= $input1 --> 저장소 목록/배열 제거1. 이제 Remove1에서 일치하는 값만 원래 inputFile에서 제거됩니다. 각 코어에 대해 계속 작업하세요.

답변1

@SatoKatsura는 이미 댓글에서 첫 번째 질문에 답변했습니다.awk -v cutoff=299851915672 'FNR == 1 || $1+0 > cutoff+0' inputFile

두 번째 질문에서 질문한 내용을 설명하기는 어렵지만(알고리즘이나 의사 코드로 질문을 업데이트할 수 있습니까?), 프로세스의 많은(50?) 인스턴스를 한 번에 실행하고 싶은 것처럼 들립니다(CPU 코어당 한 번 시스템). ). 그렇다면 파일을 50개의 작은 파일로 올바르게 분할하기 시작한 것입니다.

퍼즐에서 빠진 조각은 프로세스를 병렬로 실행하려면 GNU parallel(또는 옵션 xargs사용 )를 사용해야 한다는 것입니다. -P예를 들어:

find . -type f -name 'inputFile-*' -print0 |
    parallel -n 1 \
    awk -v cutoff=299851915672 \
      \'FNR == 1 \|\| \$1+0 > cutoff+0 {print \> FILENAME".out"}\'

(아래 참고 1, 2, 3 참조)

parallel기본적으로 시스템에서는 코어당 하나의 프로세스가 실행됩니다. -j동시 작업 수를 지정하는 옵션을 사용하여 이를 재정의 할 수 있습니다 .

스크립트 awk는 각 입력 파일의 출력을 .out동일한 이름과 추가 확장자를 가진 파일에 저장합니다(예: inputFile-1-> ) inputFile-1.out. 다시 하나의 큰 파일로 병합하려면 다음을 사용할 수 있습니다 cat.

cat inputFile*.out > complete.output.txt
rm -f *.out

참고 1: 실행하려는 명령줄에서 따옴표 및 기타 특수 문자(예:,,,, 등)를 이스케이프하려면 백슬래시를 사용해야 합니다 |. 스크립트를 별도의 파일(첫 번째 줄로 사용)에 저장하고 를 사용하여 실행 가능하게 만든 다음 스크립트를 병렬로 실행하는 것이 더 쉬울 것입니다.$>&;parallelawk#!/usr/bin/awk -fchmod

참고 2: 귀하가 실제로 요구하는 것이 무엇인지 모르기 때문에 이것이 정확히 귀하가 요구하는 것을 수행하지 못할 수도 있습니다. 여러 파일을 병렬로 처리하는 방법에 대한 일반적인 예입니다. awk(이해할 수 없는) 요구 사항을 충족하려면 스크립트를 거의 확실히 변경해야 합니다.

참고 3: 여러 프로세스를 병렬로 실행하여 절약한 시간은 입력을 여러 파일로 분할하는 데 필요한 시간과 awk각 파일에 대해 새 프로세스 인스턴스(예: 스크립트)를 시작하는 오버헤드보다 훨씬 크다는 것을 알 수 있습니다. 문서. 이는 파일의 성격과 크기, 그리고 각 파일에 대해 수행되는 처리의 성격에 따라 달라집니다. 병렬로 실행한다고 해서 항상 결과를 더 빨리 얻는다는 의미는 아닙니다. 또는 수행 중인 작업이 너무 복잡하여 이해하기 어렵고 다른 데이터와 함께 복제하기 어려울 수도 있습니다.

답변2

전체 파일을 읽지 않을 수 있나요? 예: 정렬되었으므로 이진 검색을 수행하여 관련 행의 바이트를 찾을 수 있습니다. 정렬된 텍스트 파일의 이진 검색그리고https://gitlab.com/ole.tange/tangetools/blob/master/bsearch/bsearch

대부분의 행 처리를 피할 수 있나요? 예, 관련 줄을 찾으면 나머지 부분을 복사할 수 있습니다.

이 바이트를 사용하면 head1줄 헤더에 대한 작업을 수행하고 tail발견된 바이트에서 작업을 수행할 수 있습니다.

관련 정보