Grep tìm kiếm hai từ trong một dòng


46

Tôi đã cố gắng tìm cách lọc một dòng có chữ "chanh" và "gạo" trong đó. Tôi biết cách tìm "chanh" hoặc "gạo" nhưng không phải hai người họ. Họ không cần phải ở bên cạnh người khác, chỉ cần một dòng văn bản giống nhau.


1
Để tìm tất cả các chuỗi trong một tệp, bạn có thể chạy grep trong vòng lặp FOR: unix.stackexchange.com/a/462445/43233
Noam Manos

Câu trả lời:


62

"Cả hai trên cùng một dòng" có nghĩa là "'cơm" theo sau là các ký tự ngẫu nhiên theo sau là' chanh 'hoặc ngược lại ".

Trong regex đó là rice.*lemonhoặc lemon.*rice. Bạn có thể kết hợp điều đó bằng cách sử dụng |:

grep -E 'rice.*lemon|lemon.*rice' some_file

Nếu bạn muốn sử dụng regex bình thường thay vì mở rộng ( -E), bạn cần dấu gạch chéo ngược trước |:

grep 'rice.*lemon\|lemon.*rice' some_file

Ví dụ, đối với nhiều từ nhanh hơn một chút và thường dễ sử dụng nhiều cuộc gọi hơn grep:

grep rice some_file | grep lemon | grep chicken

Dòng cuối cùng của bạn là một kết hợp không phân biệt không? Để dí dỏm: các grep ricedòng tìm thấy có chứa rice. Nó được đưa vào grep lemontrong đó sẽ chỉ tìm thấy các dòng có chứa chanh .. và như vậy. Trong khi OP - cũng như các câu trả lời trước của bạn - đang cho phép bất kỳ [cơm | chanh | gà]
javadba

Phiên bản tập lệnh: Askubfox.com/a/879253/5696
Jeff

@Florian Diesch - Tâm giải thích tại sao |cần phải trốn thoát grep? Cảm ơn!
chạy trốn

1
@fugitive egrepsử dụng regex mở rộng trong đó |được hiểu là logic OR. grepmặc định cho regex cơ bản, ở đâu \|HOẶC
Sergiy Kolodyazhnyy

Như đã nêu trong greptrang của, egrepkhông được dùng nữa và nên được thay thế bằng grep -E. Tôi lấy tự do để chỉnh sửa câu trả lời cho phù hợp.
tráng miệng

26

Bạn có thể chuyển đầu ra của lệnh grep đầu tiên sang một lệnh grep khác và nó sẽ khớp với cả hai mẫu. Vì vậy, bạn có thể làm một cái gì đó như:

grep <first_pattern> <file_name> | grep <second_pattern>

hoặc là,

cat <file_name> | grep <first_pattern> | grep <second_pattern>

Thí dụ:

Hãy thêm một số nội dung vào tập tin của chúng tôi:

$ echo "This line contains lemon." > test_grep.txt
$ echo "This line contains rice." >> test_grep.txt
$ echo "This line contains both lemon and rice." >> test_grep.txt
$ echo "This line doesn't contain any of them." >> test_grep.txt
$ echo "This line also contains both rice and lemon." >> test_grep.txt

Tệp này chứa gì:

$ cat test_grep.txt 
This line contains lemon.
This line contains rice.
This line contains both lemon and rice.
This line doesn't contain any of them.
This line also contains both rice and lemon.

Bây giờ, hãy grep những gì chúng ta muốn:

$ grep rice test_grep.txt | grep lemon
This line contains both lemon and rice.
This line also contains both rice and lemon.

Chúng tôi chỉ nhận được các dòng mà cả hai mẫu phù hợp. Bạn có thể mở rộng điều này và chuyển đầu ra sang một lệnh grep khác để khớp "VÀ" hơn nữa.


21

Mặc dù câu hỏi yêu cầu 'grep', tôi nghĩ rằng có thể hữu ích khi đăng một giải pháp 'awk' đơn giản:

awk '/lemon/ && /rice/'

Điều này có thể dễ dàng được mở rộng với nhiều từ hơn hoặc các biểu thức boolean khác bên cạnh 'và'.


11

Một ý tưởng khác để tìm các trận đấu theo bất kỳ thứ tự nào là sử dụng:

grep với tùy chọn -P (Tương thích Perl) và biểu thức chính diện tích cực(?=(regex)) :

grep -P '(?=.*?lemon)(?=.*?rice)' infile

hoặc bạn có thể sử dụng dưới đây, thay vào đó:

grep -P '(?=.*?rice)(?=.*?lemon)' infile
  • Các .*?phương tiện phù hợp với bất kỳ ký tự .nào xuất hiện 0 hoặc nhiều lần *trong khi chúng là tùy chọn theo sau bởi một mẫu ( ricehoặc lemon). Điều này ?làm cho mọi thứ tùy chọn trước nó (có nghĩa là không hoặc một lần mọi thứ khớp với nhau .*)

(?=pattern): Cái nhìn tích cực: Cấu trúc của cái nhìn tích cực là một cặp dấu ngoặc đơn, với dấu ngoặc đơn mở đầu theo sau là một dấu hỏi và dấu bằng.

Vì vậy, điều này sẽ trả về tất cả các dòng có chứa cả hai lemonricetheo thứ tự ngẫu nhiên. Ngoài ra, điều này sẽ tránh sử dụng |s và nhân đôi grep.


Liên kết ngoài: Chủ đề Grep nâng cao Nhìn tích cực - GREP dành cho nhà thiết kế


5
grep -e foo -e goo

Sẽ trả lại trận đấu cho cả foo hoặc goo


1

Nếu chúng tôi thừa nhận rằng việc cung cấp một câu trả lời không grepdựa trên là có thể chấp nhận được, như câu trả lời trên dựa trên awk, tôi sẽ đề xuất một perldòng đơn giản như:

$ perl -ne 'print if /lemon/ and /rice/' my_text_file

Việc tìm kiếm có thể bỏ qua trường hợp với một số / tất cả các từ như /lemon/i and /rice/i. Trên hầu hết các máy Unix / Linux, perl được cài đặt cũng như awk.


Từ chối!!! ;) Bởi vì nó vô nghĩa .. :)
An0n

0

Đây là một kịch bản để tự động hóa giải pháp đường ống grep:

#!/bin/bash

# Use filename if provided as environment variable, or "foo" as default
filename=${filename-foo}

grepand () {
# disable word splitting and globbing
IFS=
set -f
if [[ -n $1 ]]
then
grep -i "$1" ${filename} | filename="" grepand "${@:2}"
else
# If there are no arguments, assume last command in pipe and print everything
cat
fi
}

grepand "$@"

1
Điều này có lẽ nên được thực hiện bằng cách sử dụng một hàm đệ quy, thay vì xây dựng một chuỗi lệnh và evaling nó, nó dễ dàng bị phá vỡ
muru

@muru Hãy đề nghị chỉnh sửa. Tôi đánh giá cao nhận xét.
Jeff

1
Chỉnh sửa nó sẽ làm quá nhiều việc viết lại, vì vậy tôi sẽ không làm điều đó. Nếu bạn muốn thêm nó, đây là những gì tôi tưởng tượng nó sẽ giống như: paste.ubfox.com/23915379
muru
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.