Sử dụng dấu sao đăng nhập grep


88

Tôi đang cố gắng tìm kiếm chuỗi con "abc" trong một tệp cụ thể trong linux / bash

Vì vậy tôi làm:

grep '*abc*' myFile

Nó không trả lại gì.

Nhưng nếu tôi làm:

grep 'abc' myFile

Nó trả về các kết quả phù hợp một cách chính xác.

Bây giờ, đây không phải là vấn đề đối với tôi. Nhưng điều gì sẽ xảy ra nếu tôi muốn chuyển sang chuỗi phức tạp hơn, hãy nói

*abc * def *

Tôi sẽ thực hiện nó như thế nào bằng cách sử dụng grep?


3
Bản thân grep không hỗ trợ ký tự đại diện trên hầu hết các nền tảng. Bạn phải sử dụng egrep để sử dụng các ký tự đại diện. Vỏ có một cú pháp khác. "*" trong shell là <chuỗi bất kỳ>. Trong egrep, đó là một toán tử cho biết "0 với nhiều thực thể trước đó". Trong grep, nó chỉ là một ký tự thông thường.
PanCrit

@PanCrit: *có nghĩa tương tự trong grep và egrep: nó là một bộ định lượng có nghĩa là không hoặc nhiều hơn nguyên tử trước đó. Đó là một khái niệm hoàn toàn khác so với các ký tự đại diện được sử dụng bởi shell.
Alan Moore

Câu trả lời:


123

Dấu hoa thị chỉ là một toán tử lặp lại , nhưng bạn cần cho nó biết những gì bạn lặp lại. /*abc*/khớp với một chuỗi có chứa ab và không hoặc nhiều hơn c (vì * thứ hai nằm trên c; chuỗi đầu tiên là vô nghĩa vì không có gì để lặp lại). Nếu bạn muốn khớp với bất kỳ thứ gì, bạn cần phải nói .*- dấu chấm có nghĩa là bất kỳ ký tự nào ( trong một số nguyên tắc nhất định ). Nếu bạn muốn chỉ khớp với abc, bạn có thể nói grep 'abc' myFile. Đối với kết hợp phức tạp hơn, bạn cần sử dụng .*- grep 'abc.*def' myFilesẽ so khớp một chuỗi chứa abc theo sau là def với một cái gì đó tùy chọn ở giữa.

Cập nhật dựa trên nhận xét:

*trong một biểu thức chính quy không hoàn toàn giống với * trong bảng điều khiển. Trong bảng điều khiển, * là một phần của cấu trúc hình cầu và chỉ hoạt động như một ký tự đại diện (ví dụ: ls *.logsẽ liệt kê tất cả các tệp kết thúc bằng .log). Tuy nhiên, trong biểu thức chính quy, * là một bổ ngữ, có nghĩa là nó chỉ áp dụng cho ký tự hoặc nhóm đứng trước nó. Nếu bạn muốn * trong biểu thức chính quy hoạt động như một ký tự đại diện, bạn cần sử dụng .*như đã đề cập trước đó - dấu chấm là một ký tự đại diện và dấu sao, khi sửa đổi dấu chấm, có nghĩa là tìm một hoặc nhiều dấu chấm; I E. tìm một hoặc nhiều ký tự bất kỳ.


1
Tôi nghĩ rằng người hỏi đã nhầm lẫn về sự khác biệt giữa ký tự đại diện shell và biểu thức chính quy. Tôi cũng nghi ngờ rằng biểu thức phức tạp hơn sẽ là: grep 'abc. * Def' (có ít nhất một khoảng trắng - có thể là hai như tôi đã viết).
Jonathan Leffler,

1
Trên thực tế, người đặt câu hỏi dường như không hiểu rằng 'abc' không giống với '^ abc $' :-D
Massa

1
Có, tôi đã nhầm lẫn giữa biểu thức toàn cầu và biểu thức chính quy đầy đủ. Tôi sử dụng dấu * không có dấu chấm để có nghĩa là khớp với bất kỳ thứ gì trên shell.
Saobi

1
grep *có nghĩa là "0 trở lên" và grep là tham lam theo mặc định. Lưu ý rằng trong grep cơ bản biểu thức thông thường các metacharacters ?, +, {, |, (, và )mất ý nghĩa đặc biệt của họ. Thông tin thêm: regexps grep
KrisWebDev

25

Ký tự dấu chấm có nghĩa là khớp với bất kỳ ký tự nào, vì vậy .*có nghĩa là không có hoặc nhiều lần xuất hiện của bất kỳ ký tự nào. Bạn có thể muốn sử dụng .*hơn là chỉ *.


Dấu chấm là một ký tự meta chấp nhận bất kỳ ký tự nào ngoại trừ các dòng mới .
Abhishek Kamal

12

"Dấu sao" chỉ có ý nghĩa nếu có một cái gì đó ở phía trước của nó. Nếu không có công cụ (trong trường hợp này là grep) có thể coi đó là một lỗi. Ví dụ:

'*xyz'    is meaningless
'a*xyz'   means zero or more occurrences of 'a' followed by xyz

5
Dấu * không vô nghĩa; nó chỉ không có nghĩa thông thường (lặp lại) mà có nghĩa là "Tôi là một ngôi sao". Nó sẽ khớp với một dòng chứa một ngôi sao theo sau là x, y và z.
Jonathan Leffler

2
@Jonathan Nó phụ thuộc vào công cụ.

7

Sử dụng grep -P - cho phép hỗ trợ các biểu thức chính quy kiểu Perl.

grep -P "abc.*def" myfile

6

Ví dụ, biểu thức bạn đã thử, giống như những biểu thức hoạt động trên dòng lệnh shell trong Linux, được gọi là " hình cầu ". Biểu thức Glob không phải là biểu thức chính quy đầy đủ , đó là những gì grep sử dụng để chỉ định các chuỗi cần tìm. Đây là (cũ, nhỏ) bài đăng về sự khác biệt. Các biểu thức toàn cầu (như trong "ls *") được chính trình bao thông dịch.

Có thể dịch từ hình cầu sang RE, nhưng bạn thường cần làm như vậy trong đầu.


1
Nó chỉ là một khối cầu nếu nó được phân tích cú pháp bởi shell. Vì anh ta đang bảo toàn chuỗi tìm kiếm bên trong các dấu ngoặc kép, shell sẽ để nguyên chuỗi và chuyển nó nguyên vẹn trong argv sang grep.
Trình biên dịch dễ thấy

4

Bạn không sử dụng biểu thức chính quy, vì vậy biến thể grep mà bạn lựa chọn phải là fgrep, sẽ hoạt động như bạn mong đợi.


2
fgrephiện không được dùng nữa, grep -fnên được sử dụng thay thế.
Prometheus

1
Đó là "grep -F". Good ol 'fgrep có thể "không được dùng nữa", nhưng họ sẽ không lấy nó đi khi tôi vẫn còn sống.
Andrew Beals


1

Đây có thể là câu trả lời bạn đang tìm kiếm:

grep abc MyFile | grep def

Chỉ có điều là ... nó sẽ xuất ra các dòng "def" trước HOẶC sau "abc"


1

Điều này đã làm việc cho tôi:

grep ". * $ {expr}" - có dấu ngoặc kép, đứng trước dấu chấm. Trong đó "expr" là bất kỳ chuỗi nào bạn cần ở cuối dòng.

Các công tắc bổ sung unix grep w / out.


0

'*' hoạt động như một bổ ngữ cho mục trước đó. Vì vậy, 'abc * def' tìm kiếm 'ab' theo sau là 0 hoặc nhiều hơn 'c's follwed by' def '.

Những gì bạn có thể muốn là 'abc. * Def' tìm kiếm 'abc' theo sau là bất kỳ số ký tự nào, được đặt sau bởi 'def'.

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.