*
có một đặc biệt có nghĩa là cả hai như là một vỏ globbing ký tự ( "ký tự đại diện") và như là một biểu thức chính quy metacharater . Bạn phải tính đến cả hai, mặc dù nếu bạn trích dẫn biểu thức chính quy của mình thì bạn có thể ngăn vỏ đặc biệt xử lý nó và đảm bảo rằng nó chuyển nó không thay đổi grep
. Mặc dù về mặt khái niệm tương tự nhau, những gì *
có nghĩa là vỏ hoàn toàn khác với ý nghĩa của nó grep
.
Đầu tiên , vỏ được coi *
là ký tự đại diện.
Bạn đã nói:
Cho dù biểu thức được đính kèm trong dấu ngoặc kép không làm cho sự khác biệt.
Điều đó phụ thuộc vào những tập tin tồn tại trong bất kỳ thư mục nào bạn có mặt khi bạn chạy lệnh. Đối với các mẫu có chứa dấu phân cách thư mục /
, nó có thể phụ thuộc vào tệp nào tồn tại trên toàn bộ hệ thống của bạn. Bạn phải luôn trích dẫn các biểu thức chính quy cho grep
- và các trích dẫn đơn thường là tốt nhất-- trừ khi bạn chắc chắn rằng mình ổn với chín loại biến đổi có khả năng gây ngạc nhiên mà trình bao thực hiện trước khi thực hiện grep
lệnh.
Khi shell gặp một *
ký tự không được trích dẫn , nó sẽ có nghĩa là "không hoặc nhiều hơn bất kỳ ký tự nào" và thay thế từ có chứa nó bằng một danh sách tên tệp khớp với mẫu. (Tên tệp bắt đầu bằng .
được loại trừ - trừ khi mẫu của bạn bắt đầu bằng .
hoặc bạn đã định cấu hình trình bao của mình để bao gồm chúng.) Điều này được gọi là globalbing - và cũng bởi tên mở rộng tên tệp và mở rộng tên đường dẫn .
Hiệu ứng grep
thường sẽ là tên tệp phù hợp đầu tiên được lấy làm biểu thức chính quy - ngay cả khi người đọc khá rõ ràng rằng nó không có nghĩa là một biểu thức thông thường - trong khi tất cả các tên tệp khác được liệt kê tự động từ bạn global được lấy làm tập tin bên trong để tìm kiếm kết quả khớp. (Bạn không nhìn thấy danh sách - nó được chuyển qua một cách ngẫu nhiên grep
.) Bạn hầu như không bao giờ muốn điều này xảy ra.
Lý do điều này đôi khi không phải là một vấn đề - và trong trường hợp cụ thể của bạn, ít nhất là cho đến nay , nó đã không - là điều đó *
sẽ bị bỏ lại một mình nếu tất cả những điều sau đây là đúng :
Không có tập tin nào có tên trùng khớp. ... Hoặc bạn đã vô hiệu hóa hình cầu trong vỏ của bạn, thường là set -f
hoặc tương đương set -o noglob
. Nhưng điều này là không phổ biến và bạn có thể sẽ biết bạn đã làm nó.
Bạn đang sử dụng hệ vỏ có hành vi mặc định là để *
yên khi không có tên tệp phù hợp. Đây là trường hợp trong Bash, mà bạn có thể đang sử dụng, nhưng không phải trong tất cả các shell kiểu Bourne. (Ví dụ, hành vi mặc định trong Zsh shell phổ biến là dành cho các khối u để (a) mở rộng hoặc (b) tạo ra lỗi.) ... Hoặc bạn đã thay đổi hành vi này của vỏ của mình - cách thực hiện khác nhau trên vỏ.
Bạn chưa khác nói với shell của bạn để cho phép những đống để được thay thế bằng gì khi không có file phù hợp, cũng không phải để thất bại với một thông báo lỗi trong tình huống này. Trong Bash, điều đó đã được thực hiện bằng cách bật tùy chọnnullglob
hoặc failglob
shell tương ứng.
Đôi khi bạn có thể dựa vào # 2 và # 3 nhưng hiếm khi bạn có thể dựa vào # 1. Một grep
lệnh có mẫu không được trích dẫn hiện hoạt động có thể ngừng hoạt động khi bạn có các tệp khác nhau hoặc khi bạn chạy nó từ một nơi khác. Trích dẫn biểu hiện thường xuyên của bạn và vấn đề biến mất.
Sau đó, các grep
lệnh xử lý *
như một lượng hóa.
Các câu trả lời khác - chẳng hạn như câu trả lời của Sergiy Kolodyazhnyy và bởi kos - cũng giải quyết khía cạnh này của câu hỏi này, theo những cách khác nhau. Vì vậy, tôi khuyến khích những người chưa đọc chúng làm như vậy, trước hoặc sau khi đọc phần còn lại của câu trả lời này.
Giả sử điều *
đó làm cho nó thành grep - mà trích dẫn phải đảm bảo - grep
sau đó lấy nó để có nghĩa là mục trước nó có thể xảy ra bất kỳ số lần nào , thay vì phải xảy ra chính xác một lần . Nó vẫn có thể xảy ra một lần. Hoặc nó có thể không có mặt ở tất cả. Hoặc nó có thể được lặp đi lặp lại. Văn bản phù hợp với bất kỳ khả năng nào sẽ được khớp.
"Mục" có nghĩa là gì?
Một nhân vật duy nhất . Kể từ b
trận đấu một chữ b
, b*
phù hợp với không hay nhiều b
s, do đó ab*c
phù hợp ac
, abc
, abbc
, abbbc
vv
Tương tự như vậy, kể từ khi .
trận đấu bất kỳ ký tự , .*
phù hợp với không hoặc nhiều ký tự 1 , do đó a.*c
trận đấu ac
, akc
, ahjglhdfjkdlgjdfkshlgc
, thậm chí acccccchjckhcc
vv Hoặc
Một lớp nhân vật . Kể từ [xy]
trận đấu x
hay y
, [xy]*
trận đấu zero ký tự trở lên trong đó mỗi một là một trong hai x
hoặc y
, do đó p[xy]*q
phù hợp pq
, pxq
, pyq
, pxxq
, pxyq
, pyxq
, pyyq
, pxxxq
, pxxyq
,, vv
Điều này cũng áp dụng đối với tốc ký hình thức của các tầng lớp nhân vật như \w
, \W
, \s
, và \S
. Vì \w
khớp với bất kỳ ký tự từ nào, \w*
khớp với 0 hoặc nhiều ký tự từ. Hoặc là
Một nhóm . Kể từ \(bar\)
trận đấu bar
, \(bar\)*
trận đấu bằng không hoặc nhiều bar
s, do đó foo\(bar\)*baz
phù hợp foobaz
, foobarbaz
, foobarbarbaz
, foobarbarbarbaz
vv
Với các tùy chọn -E
hoặc -P
, hãy grep
coi biểu thức thông thường của bạn là ERE hoặc PCRE tương ứng, thay vì BRE , và sau đó các nhóm được bao quanh (
)
thay vì \(
\)
, sau đó bạn sẽ sử dụng (bar)
thay vì \(bar\)
và foo(bar)baz
thay vì foo\(bar\)baz
.
man grep
ở phần cuối có thể giải thích hợp lý về cú pháp BRE và ERE, cũng như liệt kê tất cả các tùy chọn dòng lệnh grep
chấp nhận ở đầu. Tôi khuyên bạn nên sử dụng trang thủ công đó dưới dạng tài nguyên và tài liệu GNU Grep và trang hướng dẫn / tham khảo này (mà tôi đã liên kết với một số trang trên, ở trên).
Để thử nghiệm và học tập grep
, tôi khuyên bạn nên gọi nó bằng một mẫu nhưng không có tên tệp. Sau đó, nó nhận đầu vào từ thiết bị đầu cuối của bạn. Nhập dòng; các dòng được lặp lại cho bạn là những dòng chứa văn bản mẫu của bạn phù hợp. Để thoát, nhấn Ctrl+ Dở đầu một dòng, báo hiệu kết thúc đầu vào. (Hoặc bạn có thể nhấn Ctrl+ Cnhư với hầu hết các chương trình dòng lệnh.) Ví dụ:
grep 'This.*String'
Nếu bạn sử dụng --color
cờ, grep
sẽ làm nổi bật các phần cụ thể của các dòng khớp với biểu thức chính quy của bạn, điều này rất hữu ích cho cả việc tìm ra biểu thức chính quy làm gì và tìm kiếm những gì bạn đang tìm kiếm khi bạn làm. Theo mặc định, người dùng Ubuntu có bí danh Bash gây ra grep --color=auto
để chạy - đủ cho mục đích này - khi bạn chạy grep
từ dòng lệnh, do đó bạn có thể không cần phải vượt qua --color
thủ công.
1 Do đó, .*
trong một biểu thức chính quy có nghĩa là những gì *
có nghĩa là trong một vỏ toàn cầu. Tuy nhiên, điểm khác biệt là grep
tự động in các dòng có chứa kết quả khớp của bạn ở bất kỳ đâu trong đó, do đó, thông thường không cần thiết phải có .*
ở đầu hoặc cuối của biểu thức thông thường.
* != any number of unknown characters
. đọc tài liệu.)