Sự khác biệt giữa tập tin grep apple và tập tin grep táo táo là gì?


22

Sự khác biệt giữa grep apple filevà là grep "apple" filegì? Việc đặt dấu ngoặc kép làm gì? Cả hai dường như làm việc và làm cùng một điều chính xác (hiển thị cùng một dòng).

Câu trả lời:


45

Các dấu ngoặc kép có ảnh hưởng đến những ký tự mà shell của bạn coi là đặc biệt và có ý nghĩa cú pháp. Trong ví dụ của bạn, điều này không tạo ra sự khác biệt vì applekhông chứa các ký tự như vậy.

Nhưng hãy xem xét một ví dụ khác: grep apple tree filesẽ tìm kiếm từ appletrong tệp treefiletrong khi đó grep "apple tree" filesẽ tìm kiếm từ apple treetrong tệp file. Các dấu ngoặc kép cho bash, rằng không gian từ trong "apple tree"không bắt đầu một tham số mới nhưng sẽ là một phần của tham số hiện tại. grep apple\ tree filesẽ tạo ra kết quả tương tự, vì \bảo bash bỏ qua ý nghĩa đặc biệt của nhân vật sau và đối xử với nó theo nghĩa đen.


2
Điều này cũng có thể nhìn thấy với các ký tự đại diện. Nếu bạn làm grep a*b equations.txtthì nó sẽ tìm kiếm a*b, trừ khi có một tệp trong thư mục hiện tại bắt đầu bằng a và kết thúc bằng b, trong trường hợp đó (vì (ba) sh sẽ mở rộng tên tệp trên dòng lệnh) grep sẽ được gọi với hoàn thành các thông số khác nhau, dẫn đến kết quả khác nhau. Đây thường là một vấn đề với find, vì một lệnh như thế find . -name *.txtsẽ dẫn đến hành vi không mong muốn, nếu có một tệp txt trong thư mục hiện tại. Tốt hơn là sử dụng dấu ngoặc kép trong trường hợp này.
SztupY

4
Một điểm quan trọng khác là sự khác biệt giữa dấu ngoặc kép ( ") và dấu ngoặc đơn ( '). Dấu ngoặc đơn ngăn cách giải thích các ký tự nhất định như $, trong khi dấu ngoặc kép cho phép giải thích. Ví dụ: grep '${USER}'sẽ tìm văn bản ${USER}, trong khi đó grep "${USER}"sẽ tìm văn bản mà biến USERchứa (ví dụ johnstacen).
Paddy Landau

23

Dấu ngoặc kép cho phép đánh giá, dấu ngoặc đơn ngăn đánh giá, không có dấu ngoặc kép cho phép mở rộng ký tự đại diện, khi được sử dụng trên dòng lệnh. Như ví dụ giả định:

[user@work test]$ ls .
A.txt B.txt C.txt D.cpp

# The following is the same as writing echo 'A.txt B.txt C.txt D.cpp'
[user@work test]$ echo *
A.txt B.txt C.txt D.cpp

[user@work test]$ echo "*"
*

[user@work test]$ echo '*'
*

# The following is the same as writing echo 'A.txt B.txt C.txt'
[user@work test]$ echo *.txt
A.txt B.txt C.txt

[user@work test]$ echo "*.txt"
*.txt

[user@work test]$ echo '*.txt'
*.txt

[user@work test]$ myname=is Fred; echo $myname
bash: Fred: command not found

[user@work test]$ myname=is\ Fred; echo $myname
is Fred

[user@work test]$ myname="is Fred"; echo $myname
is Fred

[user@work test]$ myname='is Fred'; echo $myname
is Fred

Hiểu cách trích dẫn công việc là mấu chốt để hiểu Bash. Ví dụ:

# for will operate on each file name separately (like an array), looping 3 times.
[user@work test]$ for f in $(echo *txt); do echo "$f"; done;
A.txt
B.txt
C.txt

# for will see only the string, 'A.txt B.txt C.txt' and loop just once.
[user@work test]$ for f in "$(echo *txt)"; do echo "$f"; done;
A.txt B.txt C.txt

# this just returns the string - it can't be evaluated in single quotes.
[user@work test]$ for f in '$(echo *txt)'; do echo "$f"; done;
$(echo *txt)

Bạn có thể sử dụng dấu ngoặc đơn để truyền lệnh thông qua một biến. Báo giá đơn sẽ ngăn chặn đánh giá. Báo giá kép sẽ đánh giá.

# This returns three distinct elements, like an array.
[user@work test]$ echo='echo *.txt'; echo $($echo)
A.txt B.txt C.txt

# This returns what looks like three elements, but it is actually a single string.
[user@work test]$ echo='echo *.txt'; echo "$($echo)"
A.txt B.txt C.txt

# This cannot be evaluated, so it returns whatever is between quotes, literally.
[user@work test]$ echo='echo *.txt'; echo '$($echo)'
$($echo)

Bạn có thể sử dụng dấu ngoặc đơn bên trong dấu ngoặc kép và bạn có thể sử dụng dấu ngoặc kép bên trong dấu ngoặc kép, nhưng dấu ngoặc kép bên trong dấu ngoặc đơn không nên được thực hiện (không thoát chúng) sẽ không được đánh giá, chúng sẽ được hiểu theo nghĩa đen. Các trích dẫn đơn trong các trích dẫn đơn không nên được thực hiện (mà không thoát chúng).

Bạn sẽ cần có được sự hiểu biết thấu đáo về các trích dẫn để sử dụng Bash một cách hiệu quả. Rất quan trọng!

Theo nguyên tắc chung, tôi không sử dụng dấu ngoặc kép nếu tôi muốn Bash mở rộng thứ gì đó thành các phần tử (như một mảng), tôi sử dụng dấu ngoặc đơn cho các chuỗi ký tự không bị thay đổi và tôi sử dụng dấu ngoặc kép tự do cho các biến có khả năng trả về bất kỳ loại chuỗi nào. Điều này là để đảm bảo rằng không gian và các ký tự đặc biệt sẽ được bảo tồn.


Làm thế nào bạn sẽ sử dụng dấu ngoặc kép bên trong dấu ngoặc kép ??? Đó có phải là một lỗi đánh máy? Và tại sao tôi nên thoát dấu ngoặc kép trong dấu ngoặc đơn thay thế? Tôi đoán bạn có thể trộn các câu lên có thể?
Chỉ huy Byte

@ByteCommander Có khái niệm dấu ngoặc kép được đặt bên trong dấu ngoặc kép được sử dụng khá phổ biến - xem bài đăng này để biết ví dụ hoạt động nổi bật. Nó thường được thực hiện để bảo vệ các chuỗi có chứa khoảng trắng, thường liên quan đến các chuỗi đường dẫn. Dấu ngoặc kép có thể được sử dụng trong một dấu ngoặc đơn có hoặc không thoát, nhưng chúng sẽ được hiểu theo nghĩa đen, nghĩa là chúng sẽ không dẫn đến đánh giá. Tôi sẽ làm rõ điểm này trong bài viết.
AsymLabs
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.