한 문자열의 첫 번째 발생부터 다른 문자열의 첫 번째 발생까지 텍스트 파일의 일부를 추출합니다.

한 문자열의 첫 번째 발생부터 다른 문자열의 첫 번째 발생까지 텍스트 파일의 일부를 추출합니다.

FOO가 처음 나타나는 부분부터 시작하여 BAR이 처음 나타나는 부분까지 대용량 텍스트 파일의 일부를 추출하려면 어떻게 해야 합니까?

제 경우에는 mysqldump로 생성된 SQL 파일의 일부를 추출하려고 합니다.

답변1

크레딧@dgig그리고@파울로피드백을 도와준 사람!결정적인 perl여기에 한 줄짜리 :

perl -lne 'if(/FOO/../BAR/){s/.*?(FOO)/$1/ if!$i++;s/BAR\K.*//&&print&&exit;print}' file

설명:

if(/FOO/../BAR/){        # perform the following actions on each line, starting
                         # with a line that contains FOO, and up to and including
                         # a line that contains BAR  
s/.*?(FOO)/$1/ if!$i++;  # only on the first line that contains FOO,
                         # delete all characters before FOO  
s/BAR\K.*//&&print&&exit;# if the line contains BAR, remove characters
                         # after BAR, print the line and stop processing  
print                    # simply print the line contents

이전 답변:

크레딧@파울로간단한 sed해결책을 위해. 다음과 같이 간단하고 읽기 쉽습니다 awk.

awk '/FOO/,/BAR/' file

하지만 너무 단순할 수 있습니다. 정확히 "FOO의 첫 번째 발생에서 시작하여 BAR의 첫 번째 발생에서 끝나는 텍스트 부분"이 아닌 전체 행을 반환합니다. 나는 이것이 FOO가 첫 번째 단어이고 BAR가 마지막 단어여야 한다는 것을 의미한다고 믿습니다. 정확히 그렇게 하려면 더 복잡한 대답이 필요합니다. 에서 그 일을 해보도록 하겠습니다 perl.

간단한 경우(전체 줄 반환):

perl -lne 'print if /FOO/../BAR/' file

복잡한 경우(정확히 FOO에서 BAR까지):

perl -lne 'if(/FOO/../BAR/){$_=~s/.*?(FOO)/$1/ if!$i++;$_=~s/BAR\K.*//;print}' file

나는 범위 연산자에 변수를 할당하는 이와 동등한 솔루션을 좋아합니다.

perl -lne 'if($a=/FOO/../BAR/){$_=~s/.*?(FOO)/$1/ if$a==1;$_=~s/BAR\K.*// if$a=~/E/;print}' file

메모:추출할 텍스트의 한 부분만 있다고 가정합니다. 즉, FOO와 BAR로 구분된 첫 번째 단락 이후에 다른 FOO를 만나면 안 됩니다.

그렇지 않으면 간단한 사례는 이미 다음에서 더 이상 간단하지 않습니다 awk.

awk '/FOO/,/BAR/ {print; if ($0~/BAR/) {exit} }' file

그리고 perl:

perl -lne '(print&&/BAR/&&exit) if /FOO/../BAR/' file

복잡하고 더욱 세련된 솔루션은 다음과 같습니다.

perl -lne 'if(/FOO/../BAR/){$_=~s/.*?(FOO)/$1/ if!$i++;$_=~s/BAR\K.*//&&print&&exit;print}' file

그리고:

perl -lne 'if($a=/FOO/../BAR/){$_=~s/.*?(FOO)/$1/ if$a==1;$_=~s/BAR\K.*//&&print&&exit if$a=~/E/;print}' file

이 예는 문제에 조금 더 복잡함을 더해 한 줄짜리 문장이 유난히 명확하고 설명이 필요 없는 것에서 모호한 일련의 임의 문자처럼 보이는 것으로 어떻게 변하는지 보여줍니다. 필요할 때마다 추가 기능을 쉽게 추가하고 특수한 경우를 고려할 수 있는 독립형, 유지 관리 및 읽기 가능한 스크립트를 작성하는 것이 좋습니다.

답변2

이 경우에는 그렇게 어렵지 않을 것이라고 생각했습니다. 를 사용하면 sed첫 번째 FOO 발생부터 첫 번째 BAR 발생까지(시도하지는 않았지만 아마도 두 번째 FOO에서 두 번째 BAR 같은 것이 더 어려울 것입니다.)

sed -nr '/FOO/ {
/FOO/ s/[^F]+FOO/FOO/p
:a
n
/BAR/ s/([^B]+BAR).*/\1/
p
/BAR/ q
ba
}' <<<'line1
> line2 FOO text1 FOO text2
> line3
> line4 BAR text3 BAR text4
> line5'

FOO text1 FOO text2
line3
line4 BAR

관련 정보