grep khối chính xác của dòng (nội dung của tệp1) từ tệp2


9

Tôi có hai tập tin, file1file2.

Nội dung mẫu của file1là:

A B
C D
E F
G H

và nội dung của file2nó giống như:

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

Vì vậy, tôi chỉ muốn tìm kiếm toàn bộ khối file1nội dung file2. Điều này có nghĩa là đầu ra chỉ nên chứa những dòng này:

A B
C D
E F
G H

xin lưu ý rằng: - chỉ các dòng kết hợp với nhau, phải là một phần của đầu ra.


Tôi không nhận được câu hỏi của bạn. Nếu bạn chỉ muốn in nội dung chính xác file1và không có gì khác, chỉ cần sử dụng cat file1.
tự đại diện

@Wildcard anh ấy muốn xem liệu file2 có chứa chính xác nội dung giống như file1 không. Hãy suy nghĩ về nó như thể tìm kiếm một chương cụ thể trong một cuốn sách
Sergiy Kolodyazhnyy 11/07/2016

Tôi đang bỏ phiếu để mở lại điều này vì "các thành viên đã thiết lập" được tạo thành từ nhiều dòng (lúc đầu tôi không phát hiện ra điều đó), phức tạp hơn một chút so với các dòng đơn được xử lý bởi câu trả lời được chấp nhận cho câu hỏi trùng lặp được đề xuất.
Kusalananda

1
Đây không phải là về bộ. Nếu bạn muốn đánh dấu đây là một bản sao, ít nhất hãy tìm một câu hỏi khác về biểu thức nhiều dòng.
Michael Vehrs

Câu trả lời:


11

grepkhá là ngu ngốc khi nói đến các mẫu đa dòng, nhưng dịch tất cả các ký tự dòng mới \ncủa cả mẫu và văn bản để tìm kiếm thành các ký tự NUL \0trước khi so sánh chúng đã sửa lỗi này. Dịch \0trong đầu ra trở lại \nrõ ràng cũng cần thiết.

Đây là lệnh của bạn, giả sử file1có chứa mẫu bạn muốn tìm kiếm trong file2:

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

Ví dụ đầu ra cho các tệp đã cho của bạn:

A B
C D
E F
G H

Giải trình:

  • <(tr '\n' '\0' < file1)tạo ra một đối tượng giống như tệp tạm thời / ống có tên là FIFO / bằng file1với tất cả các ký tự dòng mới được dịch sang các ký tự NUL.
  • <(tr '\n' '\0' < file2)làm như vậy, nhưng cho file2.
  • grep -f PATTERN_FILE INPUT_FILEtìm kiếm (các) mẫu từ PATTERN_FILEtrong INPUT_FILE.
  • Các -alá cờ của grepphép phù hợp trên các tập tin nhị phân. Điều này là cần thiết bởi vì nếu không nó sẽ bỏ qua các tệp có chứa các ký tự không in được như thế nào \0.
  • Các -olá cờ của greplàm cho nó chỉ in chuỗi phù hợp, không phải toàn bộ dòng nơi mà nó đã được tìm thấy.
  • | tr '\0' '\n' dịch tất cả các ký tự NUL từ đầu ra của lệnh ở phía bên trái trở lại các ký tự dòng mới.

6

Sau đây là vụng về, nhưng hoạt động với GNU awk:

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

3

Chỉ để cho vui trong bash tinh khiết

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

Đây là một chút thanh lịch grep+ perl:

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

Tuy nhiên, có một bắt lớn. Nếu có một dòng mới ở cuối file1, mẫu sẽ không chính xác, nói cách khác : A B\nC D\nE F\nG H\n\n.

(Cảm ơn đặc biệt @terdon vì đã cung cấp phần perl)

Như trang phục đã lưu ý, người ta có thể sử dụng perl -0pe 's/\n(\n+$)?/\\n/g' thay cho perllệnh khác để tránh dòng mới ở cuốifile1.txt


1
Nếu có một dòng mới và đó không phải là OP muốn tìm perl -0pe 's/\n(\n+$)?/\\n/g'. Nếu không có -0các gmodificator regex là phụ.
Costas

1

Tôi không chắc chắn bạn muốn đầu ra là gì, nhưng thật dễ thực hiện với các ngôn ngữ không dành riêng cho dòng (đặc biệt là nếu cả hai tệp có thể được đọc vào bộ nhớ). Đây là một kịch bản python sẽ cho bạn biết có bao nhiêu trận đấu.

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

Bạn muốn in file1bao nhiêu lần cho phù hợp? Thay thế dòng cuối cùng bằng dòng này:

print(find * hay.count(find))

Bạn có thể đóng gói mọi thứ vào một cuộc gọi lệnh hoặc bí danh, nếu bạn thực sự muốn:

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

kết quả sẽ là tất cả các tệp có khớp văn bản chính xác


0

Đây là một cách tiếp cận khác sử dụng python (đã thử nghiệm với python3 3.5.2, không có khiếu nại từ 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]))))

Việc xử lý các đối số dòng lệnh thông qua sys.argvđược thừa nhận là đơn giản. Bạn có thể làm nhiều việc khác với giá trị trả về của finderhai memoryviewđối tượng bạn truyền vào, bên cạnh việc chuyển nó sang tuple. Mỗi SRE_Matchmục được tạo bởi iterator được trả về findercó nhiều phương thức khác nhau, một mẫu được tóm tắt trong printđầu ra ( spanví dụ, cho biết phạm vi byte của mỗi trận đấu).

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.