Làm thế nào để làm cho grep chỉ khớp nếu toàn bộ dòng khớp?


103

Tôi có những:

$ cat a.tmp
ABB.log
ABB.log.122
ABB.log.123

Tôi muốn tìm một kết hợp chính xác của ABB.log.

Nhưng khi tôi đã

$ grep -w ABB.log a.tmp
ABB.log
ABB.log.122
ABB.log.123

nó hiển thị tất cả chúng.

Tôi có thể nhận được những gì tôi muốn bằng cách sử dụng grep?

Câu trả lời:


105

Chỉ cần chỉ định các neo regexp.

grep '^ABB\.log$' a.tmp

2
Cả hai neo (^ và $) đều cần thiết.
user562374

2
Đẹp quá! Và nếu tôi đang sử dụng regex để đối sánh từ một tệp? "grep -f mẫu a.tmp" ??
green69

@ green69 Vài năm muộn, nhưng bạn có thể sử dụng sed để thêm neo trước khi đi qua các mô hình để grep:sed -r "s/^(.*)$/^\1$/" patterns.txt | egrep -f - a.tmp
randoms

155
grep -Fx ABB.log a.tmp

Từ trang grep man:

-F, --fixed-string
Diễn giải PATTERN dưới dạng (danh sách) các chuỗi cố định
-x, --line-regexp
Chỉ chọn những kết quả khớp chính xác với toàn bộ dòng.


2
không may là không thể sử dụng -F.
Johnyy

@Johnyy Không -F? bạn có ở trên Solaris không? Nếu sử dụng quá/usr/xpg4/bin/grep
Scrutinizer

9
Tôi đang sử dụng grepbên trong một tập lệnh bash và tùy chọn này tốt hơn là sử dụng một biểu thức chính quy như được đề xuất trong câu trả lời được chấp nhận. Bởi vì tôi có một số ký tự đặc biệt bên trong biến mà tôi đang tìm kiếm (như .) và tôi không phải thoát chúng khi sử dụng lệnh.
Gustavo Straube

1
câu trả lời tốt nhất IMO vì nó cho phép các ký tự đặc biệt mà không cần thoát
ReneGAED

1
Điều này tốt hơn vì nó cũng hoạt động với các biến.
ybenjira

23

Đây là những gì tôi làm, mặc dù sử dụng neo là cách tốt nhất:

grep -w "ABB.log " a.tmp

Như thế này .. nó sẽ trở lại dòng đầu tiên trận đấu
user765443

1
Điều này đòi hỏi một khoảng trống sau ABB.logđó, không phải là trường hợp chung, tức là nó sẽ thất bại trong hầu hết thời gian.
Jahid

3

Hầu hết các đề xuất sẽ không thành công nếu có quá nhiều khoảng trắng ở đầu hoặc cuối, điều này sẽ quan trọng nếu tệp được chỉnh sửa bằng tay. Điều này sẽ làm cho nó ít nhạy cảm hơn trong trường hợp đó:

grep '^[[:blank:]]*ABB\.log[[:blank:]]*$' a.tmp

Một vòng lặp while-read đơn giản trong shell sẽ thực hiện điều này một cách ngầm định:

while read file
do 
  case $file in
    (ABB.log) printf "%s\n" "$file"
  esac
done < a.tmp


1

Tôi định bổ sung thêm một số giải thích liên quan đến nỗ lực của OP và các câu trả lời khác.

Bạn cũng có thể sử dụng giải pháp của John Kugelmans như thế này:

grep -x "ABB\.log" a.tmp

trích dẫn chuỗi và thoát dấu chấm ( .) làm cho nó không cần -Fcờ nữa.

Bạn cần phải thoát khỏi .(dấu chấm) (vì nó khớp với bất kỳ ký tự nào (không chỉ .) nếu không thoát) hoặc sử dụng -Fcờ với grep. -Fcờ biến nó thành một chuỗi cố định (không phải là regex).

Nếu bạn không trích dẫn chuỗi, bạn có thể cần dấu gạch chéo ngược kép để thoát khỏi dấu chấm ( .):

grep -x ABB\\.log a.tmp


Kiểm tra:

$ echo "ABBElog"|grep -x  ABB.log
ABBElog #matched !!!
$ echo "ABBElog"|grep -x  "ABB\.log"
#returns empty string, no match


Ghi chú:

  1. -x lực để phù hợp với toàn bộ dòng.
  2. Các câu trả lời bằng cách sử dụng không có mã thoát .không có -Fcờ là sai.
  3. Bạn có thể tránh -xchuyển đổi bằng cách quấn chuỗi mẫu của mình bằng ^$. Trong trường hợp này, hãy đảm bảo rằng bạn không sử dụng -F, thay vào đó hãy thoát khỏi ., bởi vì -Fsẽ ngăn việc giải thích regex của ^$.


EDIT: (Thêm giải thích bổ sung liên quan đến @hakre):

Nếu bạn muốn so khớp một chuỗi bắt đầu bằng -, thì bạn nên sử dụng --với grep. Bất cứ điều gì sau đây --sẽ được lấy làm đầu vào (không phải tùy chọn).

Thí dụ:

echo -f |grep -- "-f"     # where grep "-f" will show error
echo -f |grep -F -- "-f"  # whre grep -F "-f" will show error
grep "pat" -- "-file"     # grep "pat" "-file" won't work. -file is the filename

Bạn đã thực sự trải nghiệm rằng -F bị thiếu trong trường hợp của bạn? Nếu vậy, bạn có thể vui lòng cho biết đó là trường hợp nào không?
hakre

@hakre Bạn đã đọc hết câu trả lời của tôi chưa? Tôi đã giải thích (khá rõ ràng) tại sao -Fsẽ không cần thiết nếu .thoát đúng cách.
Jahid

Chắc chắn rồi. Chắc chắn, tôi chỉ hỏi: Có -Fsẵn khi bạn viết điều này không? Nếu không, bạn đang sử dụng hệ thống nào? Tôi không thể tìm thấy thông tin đó trong câu trả lời của bạn cho đến nay, thậm chí bây giờ là trường hợp khi tôi đọc lại nó. Vì vậy, thực sự chắc chắn, tôi đã đọc hoàn toàn câu trả lời của bạn ít nhất hai lần. ;)
hakre

@hakre Tất nhiên -Flà đã có. (Tôi đã nói: "hoặc sử dụng -Fcờ với grep")
Jahid

Cảm ơn cho cái nhìn sâu sắc. Chỉ còn lại một câu hỏi nhỏ: Nếu -Flà câu trả lời, tại sao phải bận tâm về việc trốn thoát? Ý kiến ​​của bạn về điều đó là gì?
hakre

1

Điều này hiệu quả với tôi khi cố gắng làm điều gì đó tương tự:

grep -F ABB.log a.tmp

-1
    $ cat venky
    ABB.log
    ABB.log.122
    ABB.log.123

    $ cat venky | grep "ABB.log" | grep -v "ABB.log\."
    ABB.log
    $

    $ cat venky | grep "ABB.log.122" | grep -v "ABB.log.122\."
    ABB.log.122
    $

1
Điều này cũng sẽ khớp với các tệp kết thúc bằng ABB.log và các dấu chấm sẽ được thoát ra.
Scrutinizer

-1

Làm việc cho tôi :

grep "\bsearch_word\b" text_file > output.txt  

\b chỉ ra / thiết lập ranh giới.

Có vẻ hoạt động khá nhanh


Điều này cũng khớp với bất kỳ dòng nào chứa search_wordphân tách bằng ranh giới từ. Ví dụ: nó sẽ khớp với dòng "foo search_word bar".
Rohan Singh

-2

Đây là với HPUX, nếu nội dung của tệp có khoảng cách giữa các từ, hãy sử dụng tùy chọn này:

egrep "[[:space:]]ABC\.log[[:space:]]" a.tmp


OP muốn đối sánh toàn bộ dòng, không phải một từ được phân cách bằng dấu cách trong dòng.
Keith Thompson


-3

Tôi cần tính năng này, nhưng cũng muốn đảm bảo rằng tôi không trả về các dòng có tiền tố trước ABB.log:

  • ABB.log
  • ABB.log.122
  • ABB.log.123
  • 123ABB.log

grep "\WABB.log$" -w a.tmp

Điều này sẽ chỉ khớp nếu phần đầu \Wđược thỏa mãn, là bất kỳ ký tự nào không có khoảng trắng, vì vậy xABBxlog.
bschlueter
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.