한 줄이 포함된 대용량(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
하면 파일이 기존의 한 줄씩 처리에 더 적합해집니다.
추가 논의를 통해 이는 플랫 파일을 생성하기 위한 서지 조회라는 사실이 밝혀졌습니다. jq
OP는 다음 프로그램(내 첫 번째 프로그램)이 충분히 빠르다고 생각합니다.
#!/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