file2에서 정확한 행 블록 (file1의 내용)을 grep


9

나는 두 개의 파일을 가지고 file1와 file2.

샘플 내용 file1은 다음과 같습니다.

A B
C D
E F
G H

내용 file2은 다음과 같습니다.

A B
few other lines
E F
few more other lines
A B
C D
E F
G H
few more other lines
G H

전체 file1콘텐츠 블록 file2만 검색하고 싶습니다 . 이것은 출력에 다음 줄만 포함되어야 함을 의미합니다.

A B
C D
E F
G H

참고 :-함께 오는 줄만 출력의 일부가되어야합니다.


질문이 없습니다. 정확한 내용 만 인쇄하고 싶을 file1때는을 사용하십시오 cat file1.
— 와일드 카드

@Wildcard 그는 file2에 file1과 정확히 동일한 내용이 포함되어 있는지 확인하려고합니다. 책에서 특정 챕터를 찾는 것처럼 생각하십시오
— Sergiy Kolodyazhnyy

"집합 멤버"가 여러 줄로 구성되어 있기 때문에 이것을 다시 열겠다고 투표하고 있습니다.
— Kusalananda

1
이것은 세트에 관한 것이 아닙니다 . 이것을 중복으로 표시하려면 최소한 여러 줄 정규식에 대한 다른 질문을 찾으십시오.
— Michael Vehrs

답변:


11

grep여러 줄 패턴에 관해서는 매우 어리석지 만 \n패턴과 텍스트의 줄 바꿈 문자 를 모두 번역 하여 NUL 문자로 검색하면 \0이를 수정합니다. \0출력을 다시 번역 하는 \n것도 분명히 필요합니다.

file1검색하려는 패턴 이 포함되어 있다고 가정하면 명령은 다음과 같습니다 file2.

grep -aof <(tr '\n' '\0' < file1) <(tr '\n' '\0' < file2) | tr '\0' '\n'

주어진 파일에 대한 예제 출력 :

A B
C D
E F
G H

설명:

  • <(tr '\n' '\0' < file1)FIFO / 명명 된 파이프 / 임시 파일과 유사한 객체를 생성 file1하지만 모든 개행 문자는 NUL 문자로 변환됩니다.
  • <(tr '\n' '\0' < file2)동일하지만을 수행 file2합니다.
  • grep -f PATTERN_FILE INPUT_FILE발 패턴 (들)에 대한 검색 PATTERN_FILE에서 INPUT_FILE.
  • 이 -a플래그는 grep이진 파일에서 일치를 활성화합니다. 그렇지 않으면와 같은 인쇄 할 수없는 문자가 포함 된 파일을 건너 뛰기 때문에 필요합니다 \0.
  • of -o플래그는 grep발견 된 전체 행이 아니라 일치하는 순서 만 인쇄합니다.
  • | tr '\0' '\n' 왼쪽의 명령 출력에서 ​​모든 NUL 문자를 개행 문자로 다시 변환합니다.

6

다음은 어색하지만 GNU와 함께 작동합니다 awk.

awk -v RS="$(<file1)" '{print RT}' file2

3

순수한 배쉬에서 재미를 위해

mapfile -t <file1
while read line ; do
    [ "$line" = "${MAPFILE[i++]}" ] || { ["$line" = "$MAPFILE" ] && i=1 || i=0; }
    [ $i -eq ${#MAPFILE[*]} ] && { printf "%s\n" "${MAPFILE[@]}"; i=0; }
done <file2

3

좀 더 우아하고 grep+ perl:

$ grep -Pzo "$(perl -pe 's/\n/\\n/g' file1.txt )"  file2.txt                    
A B
C D
E F
G H

그러나 한 가지 큰 문제가 있습니다. 에 후행 줄 바꿈이 있으면 file1패턴이 올바르지 않습니다 A B\nC D\nE F\nG H\n\n. 즉, .

(펄 부분을 제공하는 @terdon에게 특별한 감사를드립니다)

costas 언급 한 바와 같이, perl -0pe 's/\n(\n+$)?/\\n/g' 다른 perl명령 대신에 줄 바꿈 줄을 피할 수 있습니다 .file1.txt


1
후행 줄 바꿈이 있고 OP가 아닌 경우 찾아야 perl -0pe 's/\n(\n+$)?/\\n/g'합니다. 없이 정규식 modificator 추가합니다. -0g
— Costas

1

출력이 무엇을 원하는지 잘 모르겠지만 독점적으로 줄 지향적이지 않은 언어 (특히 두 파일을 모두 메모리로 읽을 수있는 경우)로 쉽게 할 수 있습니다. 다음은 일치하는 항목 수를 알려주는 Python 스크립트입니다.

import sys
find = open(sys.argv[1]).read()
hay = open(sys.argv[2]).read()
print("The text occurs", hay.count(find), "times")

file1일치하는 횟수만큼 인쇄하고 싶 습니까? 마지막 줄을 다음과 같이 바꾸십시오.

print(find * hay.count(find))

실제로 원하는 경우 모든 것을 명령 줄 호출 또는 별칭으로 묶을 수 있습니다.

python -c 'import sys; print("The text occurs", open(sys.argv[2]).read().count(open(sys.argv[1]).read()), "times")' file1 file2

1
grep -lir 'A B \n D C \n whatever' ./folder_to_search

결과는 정확히 일치하는 모든 파일이됩니다


0

다음은 파이썬을 사용하는 또 다른 접근법입니다 ( python3 3.5.2에서 불만없이 테스트했습니다 pylint3 1.5.6).

""" Locate entire file contents contiguous in other file """

import sys
import re
from mmap import mmap, PROT_READ

def memmap(name):
    """ Return memoryview of readonly mmap """
    with open(name, 'rb') as file:
        return memoryview(mmap(file.fileno(), 0, access=PROT_READ))

def finder(needle, haystack):
    """ Return iterator """
    return re.compile(re.escape(needle)).finditer(haystack)

print(tuple(finder(*(memmap(name) for name in sys.argv[1:3]))))

via를 통한 명령 행 인수 처리는 매우 sys.argv간단합니다. 전달 finder하는 두 memoryview객체 에 대한 반환 값을 로 전달하는 것 외에도 많은 다른 작업을 수행 할 수 tuple있습니다. SRE_Match이터레이터가 반환 한 각 항목은 finder다양한 방법을 가지며, 샘플링은 print출력에 요약됩니다 ( span예 : 각 일치의 바이트 범위를 나타냄).

당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.