Khi nào nên sử dụng trích dẫn đơn, trích dẫn kép trong grep?


20

Trong khi cố gắng tìm kiếm một mẫu đơn giản "xin chào" trong một tệp, tất cả các hình thức grep sau đây đều hoạt động:

  • grep xin chào tập tin1
  • grep 'xin chào' tập tin1
  • grep "xin chào" tập tin1

Có một trường hợp cụ thể trong đó một trong các hình thức trên hoạt động nhưng những hình thức khác thì không. Liệu nó có làm nên sự khác biệt nếu tôi sử dụng cái này thay cho cái khác không?

Câu trả lời:


25

Điều này thực sự phụ thuộc vào vỏ của bạn. Trích dẫn (một trong hai loại) chủ yếu là để đối phó với khoảng trắng. Ví dụ, như sau:

grep hello world file1

sẽ tìm từ "xin chào" trong các tệp gọi là "thế giới" và "tệp1", trong khi

grep "hello world" file1

sẽ tìm "hello world" trong file1.

Sự lựa chọn giữa dấu ngoặc đơn hoặc dấu ngoặc kép chỉ quan trọng nếu chuỗi tìm kiếm chứa các biến hoặc các mục khác mà bạn muốn được đánh giá. Với dấu ngoặc đơn, chuỗi được thực hiện theo nghĩa đen và không có sự mở rộng nào diễn ra. Với dấu ngoặc kép, các biến được mở rộng. Ví dụ: (với lớp vỏ có nguồn gốc từ Bourne như Bash hoặc ZSH):

VAR="serverfault"
grep '$VAR' file1
grep "$VAR" file1

Đầu tiên grepsẽ tìm chuỗi ký tự "$ VAR1" trong tệp1. Cái thứ hai sẽ mở rộng biến "$ VAR" và tìm chuỗi "serverfault" trong file1.


Điều quan trọng cần lưu ý là trong câu hỏi ban đầu, grep thực sự đang nhận được các đối số chính xác giống nhau mỗi lần.
MikeyB

2
Hãy cẩn thận ở đó. $là kết thúc trong một biểu thức chính quy, vì vậy $VAR1không bao giờ thực sự khớp với bất cứ điều gì. Nó hoạt động trên GNU grep, nhưng tôi vẫn không tin vào hành vi đó. Bạn cần phải \$VAR1khớp một cách an toàn chuỗi ký tự. (Và bạn sẽ cần thêm dấu gạch chéo ngược nếu đó là dấu ngoặc kép.)
Steven Pritchard

7

James nói đúng, nhưng để thêm một số dữ liệu, tôi nghĩ rằng cách tốt nhất để suy nghĩ về nó là lập luận cho lệnh: bạn có định "xin chào" và "thế giới" là hai đối số hay "thế giới xin chào" là một tranh luận.

Ngoài ra, doublequote cho phép giải thích nhiều hơn chỉ là các biến. Chính xác những gì phụ thuộc vào vỏ của bạn, nhưng hãy kiểm tra mở rộng lịch sử, mở rộng dấu ngoặc và mở rộng tên tệp.

Cũng cần lưu ý rằng có một số trường hợp bạn cần sử dụng cả hai loại trích dẫn trong một đối số. Hãy nhớ rằng các đối số (theo mặc định) được phân cách bằng khoảng trắng, vì vậy nếu bạn không để lại bất kỳ khoảng trắng nào, bạn vẫn chỉ định cùng một đối số.

Cơ chế một đơn vị của hầu hết các shell không cho phép bất kỳ ký tự đặc biệt nào, điều đó có nghĩa là bất kỳ trường hợp nào của một đơn vị khác, ngay cả khi nó xuất hiện để thoát, kết thúc trích dẫn. Do đó, không thể truyền một chuỗi với một chuỗi đơn trong một chuỗi ký tự đơn và bạn phải sử dụng chuỗi kép. Điều này có thể là một nỗi đau khi bạn muốn vượt qua một đối số có chứa các câu đơn và một cái gì đó sẽ được giải thích, nhưng bạn không muốn. Ví dụ: nếu bạn muốn truyền chuỗi ký tự "` '$ VAR' là một biến ", bạn phải thực hiện theo cách này:

"'"'$VAR'"' is a variable"

Đó thực sự là một sự kết hợp của ba chuỗi thoát trích dẫn:

"'"
'$VAR'
"' is a variable"

hoặc, với các trích dẫn bị xóa:

'
$VAR
' is a variable

Trên thực tế, với hầu hết các shell, bạn cũng có thể làm theo cách này:

"'\$VAR' is a variable"

trong đó dấu gạch chéo ngược (" \") báo cho shell chấp nhận ký tự sau theo nghĩa đen và không thực hiện bất kỳ mở rộng nào trên nó.

Nhưng có một số trường hợp cuối cùng bạn phải thực hiện theo cách nối đa chuỗi, không phải là tôi thực sự có thể đưa ra một ví dụ ngay bây giờ.

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.