두 문자열이 처음 나타나는 사이의 파일 부분을 빠르게 추출합니다.

두 문자열이 처음 나타나는 사이의 파일 부분을 빠르게 추출합니다.

한 줄이 포함된 대용량(MB) 텍스트 파일이 있는데 string1과 string2의 첫 번째 항목 사이의 부분을 추출해야 합니다. 많은 레시피를 찾았지만 대부분은 별도의 줄에서 작업하거나 두 번째 문자열의 마지막 항목까지 추출합니다. infile, outfile, string1, string2 매개변수를 사용하여 작동하는 것을 내가 찾은 것은 다음과 같습니다.

#!/bin/bash

a="$(cat $1)"                   ## copy file1 to a

a="$(echo "${a#*"$3"}")"        ## cut up to (including) str1  

echo "${a%%"$4"*}" > $2         ## part after str1 up to str2

## where the last line may also be

printf '%s' "${a%%"$4"*}" > $2  ## part after str1 up to str2

하지만 두 버전 모두 매우 느립니다(각 파일에 대해 여러 번 반복해야 합니다). 속도를 높이는 방법?

답변1

OP와 채팅하는 동안 일부 토론에서 한 줄이 웹 쿼리의 JSON이라는 사실이 밝혀졌습니다. jq . < input_file또는 같은 도구를 사용하여 이 파일을 예쁘게 인쇄 python -mjson.tool input_file하면 파일이 기존의 한 줄씩 처리에 더 적합해집니다.

추가 논의를 통해 이는 플랫 파일을 생성하기 위한 서지 조회라는 사실이 밝혀졌습니다. jqOP는 다음 프로그램(내 첫 번째 프로그램)이 충분히 빠르다고 생각합니다.

#!/bin/bash                                                                                                                           

jq -r  < "$1" '.response.docs[] |                                                                                          
    ("    Title: "+.title[]),                                                                                                          
    ("   Authors: "+(.author|join(""))),                                                                                               
    ("    Bibcode: "+.bibcode),                                                                                                        
    ("   AltBibcode: "+(.alternate_bibcode//[] | join(" : "))),                                                                        
    ("  "+(.abstract//"NOABSTRACT")),                                                                                                  
    ""' | fmt | sed 's/^    \?//'

몇 가지 미묘한 점이 있습니다. 우리가 원하는 것은 긴 줄보다는 요약을 감싸서 출력이 를 통해 전송되는 것입니다 fmt. 이 프로그램에는 다음과 같은 속성이 있습니다. 다른 들여쓰기로 시작하는 줄아니요함께 결합하여 "제목:"과 같이 텍스트에 4/3/4/3/2 간격 패턴을 추가하세요. 그런 다음 fmt는 실제로 요약을 2개의 공백으로 들여쓰기하여 래핑합니다. 그런 다음 sed를 사용하여 다른 헤더 줄에서 3~4개의 공백을 제거합니다. 완벽하지는 않으며 긴 저자 목록도 압축될 수 있습니다. 더 나은 sed 프로그램은 작성자를 라인에 다시 연결하고, 빈 AltBibcode 항목을 제거하는 등의 작업을 수행할 수 있습니다.

출력 형식은 awk 한 줄 스크립트를 통해 사후 처리되도록 신중하게 설계되었습니다.

awk -vRS='' -vORS=$'\n\n' !/NOABSTRACT/'

요약 없이 항목을 삭제합니다.

답변2

$ sed -e 's/stringA/\n/;s/.*\n//;s/stringB.*//' file 

stringA 이전의 코드 삭제는 "stringA 이전의 모든 항목 삭제"라는 보다 명확한 방법보다는 두 단계(stringA를 개행 문자로 변경한 다음 첫 번째 줄 삭제)로 수행됩니다.첫 번째마지막 문자열 대신 stringA가 발생합니다. 다른 많은 도구(예: Python 및 Perl)와 달리 sed는 탐욕스럽지 않은 정규식을 지원하지 않습니다.

$ perl -lpe '
    my($sa, $sb) = qw/stringA stringB/;
    my $p2 = index($_, $sb);
    my $p1 = index($_, $sa)+length($sa);
    $_ = substr($_, $p1, $p2-$p1);
'  file

관련 정보