Ung Ungrep - những mẫu không phù hợp


13

Tôi đang tìm kiếm một lệnh hoặc tập lệnh để thực hiện các thao tác sau - đã cho:

file1.txt:

abcd
efgh 
ijkl
mnop

file2.txt:

123abcd123
123efgh123
123mnop123

Tôi muốn một lệnh làm một cái gì đó như thế này:

ungrep file1.txt file2.txt

và trả về như sau:

ijkl

Nói cách khác, nó cung cấp cho tôi các dòng trong file1.txt sẽ không trả về bất kỳ kết quả nào trên grep của file2.txt. Tôi biết rằng tôi có thể làm điều này bằng cách lặp qua file1.txt, grepping file2.txt cho mỗi dòng và lưu trữ kết quả, và xuất ra bất kỳ dòng nào có kết quả trống, nhưng tôi hy vọng sẽ có cách hiệu quả hơn để làm điều này.

Câu trả lời:


18

Với GNU grepsau đây sẽ hoạt động. Sử dụng -ftùy chọn, chuyển file1.txtdưới dạng "tệp mẫu" - nhưng cũng chuyển nó trong lần thứ hai dưới dạng tệp dữ liệu. Sử dụng -ođể chỉ báo cáo các phần phù hợp. Cuối cùng trích xuất những từ đó chỉ khớp một lần - những từ này tương ứng với các dòng file1.txtkhông tìm thấy từ trùng khớp file2.txt.

grep -h -o -f  file1.txt file2.txt file1.txt | sort | uniq -u
ijkl

Mô tả rất tốt. Cảm ơn và +1.
unxnut

4
Bạn có thể đạt được hiệu ứng tương tự mà không cần sự khéo léo của grep: sort file1.txt <(grep -of file1.txt file2.txt) | uniq -unhưng, giống như giải pháp của bạn, điều này chỉ hoạt động khi tệp mẫu không thực sự chứa bất kỳ siêu ký tự regex nào.
rici

@rici, đó là một điểm rất tốt
iruvar

2
Cải thiện:grep -oFf file1.txt file2.txt | sort file1.txt - | uniq -u
Stéphane Chazelas

10

Bạn có thể làm điều đó awknhư:

awk '
  NR == FNR {w[$0]; next}
  {for (i in w) if (index($0,i)) delete w[i]}
  END {for (i in w) print i}' file1.txt file2.txt

Bằng cách sử dụng index, chúng tôi đang tìm kiếm các chuỗi con thay vì khớp với các biểu thức thông thường.

Bởi vì chúng tôi xóa từ khỏi mảng ngay khi tìm thấy kết quả khớp, chúng tôi tránh các tìm kiếm không cần thiết.


1
Tôi sẽ chỉ chấp nhận điều này. Nó không gọi bất kỳ sắp xếp O (n log n) nào và không thất bại một cách kỳ lạ khi các mẫu chứa các ký tự meta regex và có thể được mở rộng để hỗ trợ các biểu thức chính quy.
Kaz

Tôi không thể tin rằng việc đánh giá đơn giản w[$0]có tác dụng phụ là thêm khóa vào mảng.
Kaz

1
@Kaz, vâng, điều đó có thể gây nhầm lẫn và bạn thấy nhiều tập lệnh không cố ý phân bổ các phần tử mảng một cách vô ý bằng cách làm if (a[$1])thay vì if ($1 in a)ví dụ. Đó là trường hợp của mọi thứ awkbao gồm cả bản gốc awknawk, nhưng nhìn vào tiêu chuẩn ngày hôm qua, tôi không thể tìm thấy nó được chỉ định.
Stéphane Chazelas

1
@Kaz Dưới đây là trích dẫn POSIX: "Ứng dụng sẽ đảm bảo rằng một chỉ số đa chiều được sử dụng với toán tử trong được ngoặc đơn. Toán tử in , kiểm tra sự tồn tại của một phần tử mảng cụ thể, sẽ không khiến phần tử đó tồn tại. tham chiếu khác đến một phần tử mảng không tồn tại sẽ tự động tạo ra nó. " Nó có thể được tìm thấy bằng cách cuộn một hoặc hai đoạn từ đây .
jw013

1
Miễn file1là không lớn (đối với một số giá trị khổng lồ), tôi thích giải pháp này vì nó không yêu cầu bất kỳ sự sắp xếp nào file2và sẽ được mong đợi sẽ hiệu quả hơn nhiều.
jw013
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.