Sự khác biệt giữa grep apple file
và là grep "apple" file
gì? 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).
Sự khác biệt giữa grep apple file
và là grep "apple" file
gì? 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:
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ì apple
khô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 file
sẽ tìm kiếm từ apple
trong tệp tree
và file
trong khi đó grep "apple tree" file
sẽ tìm kiếm từ apple tree
trong 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 file
sẽ 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.
"
) 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 USER
chứa (ví dụ johnstacen
).
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.
grep a*b equations.txt
thì nó sẽ tìm kiếma*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 *.txt
sẽ 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.