Trong bash, làm thế nào để tôi thoát khỏi dấu chấm than?


183

Tôi muốn làm một cái gì đó như bzr commit -m "It works!". Tôi có thể loại bỏ dấu chấm than bằng cách làm bzr commit -m "It works\!". Tuy nhiên, sau đó tin nhắn cam kết của tôi bao gồm dấu gạch chéo ngược. Làm cách nào để thoát dấu chấm than, trong khi vẫn bỏ qua dấu gạch chéo ngược?


1
Làm bzr commit -m "It works"!việc cũng vậy.
kba

1
Như tôi đã lưu ý trước khi lệnh bạn đặt thực sự hoạt động theo cách riêng của nó :)bzr commit -m "It works!"
h4unt3r

Một trường hợp thậm chí còn khó hiểu hơn với các trích dẫn lồng nhau: stackoverflow.com/questions/22125658/NH
Ciro Santilli

1
Mặc dù câu trả lời được chấp nhận là một cách giải quyết tốt cho các vấn đề cam kết của bạn, tôi cảm thấy đó không phải là câu trả lời cho vấn đề thực tế: mở rộng lịch sử Bash . Hãy xem xét chấp nhận câu trả lời của Dennis?
Arjan

Câu trả lời:


153

Vì bạn không phụ thuộc vào bash để mở rộng các biến trong thông điệp cam kết của mình, bạn có thể sử dụng dấu ngoặc đơn thay thế. Chuỗi trong dấu ngoặc đơn không được mở rộng bằng bash.

bzr commit -m 'This does work!' 

24
Vì câu hỏi là "Làm thế nào để tôi thoát khỏi dấu chấm than?" và không "Làm thế nào để tôi không mở rộng dấu chấm than?" Tôi không nghĩ rằng điều này là hợp lệ. Có một số lần (như khi vượt qua dấu nháy đơn và dấu chấm than trong cùng một dòng lệnh) mà điều này không hoạt động. Câu trả lời dưới đây hoạt động tốt hơn nhiều để làm những gì nhiều người cần.
Jann

7
@Jann: Bạn hoàn toàn đúng 100% về vấn đề này, nhưng tôi nghĩ vấn đề ở đây là vấn đề có rất nhiều câu hỏi về siêu người dùng: Chúng tôi có trả lời câu hỏi hay không, hoặc chúng tôi giúp mọi người giải quyết vấn đề cụ thể của họ. Tôi nghĩ cả hai cách đều có thể hữu ích và điều này đang tìm kiếm sự giúp đỡ về một vấn đề cụ thể.
Benjamin Bannier

cảm động Đây là một vấn đề cụ thể. Tôi chỉ có xu hướng muốn một câu trả lời cho câu hỏi của mình để có thể được sử dụng trong nhiều tình huống. pS: Lý do tôi thậm chí đã đề cập đến điều này là vì tôi cần chuyển cả dấu nháy đơn và dấu chấm than cho chương trình perl và tôi cần giải pháp dưới đây. :)
Jann

Tôi đồng ý với cả Benjamin và Jann nhưng đã đưa ra một downvote. Tiêu đề của câu hỏi được lập chỉ mục bởi các công cụ tìm kiếm và đó là cách tôi đến đây và có lẽ hầu hết người dùng đến đây. Đó là lý do tại sao tôi tin rằng điều quan trọng là câu hỏi thực tế phản ánh vấn đề đằng sau nó. Trong các diễn đàn khác, mọi người được khuyên (gần như bị ép buộc) hỏi chính xác những gì họ tìm kiếm. Trả lời các câu hỏi được thể hiện kém hỗ trợ cho sự chậm chạp và đó là lý do chính xác cho sự thất vọng của tôi ở đây. Như một sự thỏa hiệp / giải pháp, đề nghị của tôi là giúp điều chỉnh tiêu đề để nó phản ánh vấn đề thực tế.
ChristophK

153

Đây là một phương pháp khác nếu bạn muốn trích dẫn kép cũng như câu cảm thán:

echo "It's broken"'!'

Điều này hoạt động ngay cả khi !không ở cuối dòng.

Ví dụ:

echo "hello there"'!'" and goodbye"

Phần thưởng: Một kỹ thuật tương tự có thể được sử dụng để thoát khỏi bất kỳ văn bản nào trong Sh hoặc Bash (với sự trợ giúp của sed): xem tùy chọn đầu tiên trong câu trả lời này . Hơn nữa, nếu bạn đã bash-completioncài đặt, bạn có thể có các quote()chức năng có sẵn rồi.


4
Mẹo hay, JWD. Tôi đã không nhận ra các chuỗi bash có thể được nối bằng cách bỏ qua khoảng trắng giữa chúng.
Alan H.

Trên thực tế nếu dấu chấm than ở cuối chuỗi bạn rõ ràng echo "Happy birthday!"sẽ hoạt động như mong đợi nếu không bạn có thể thoát nó bằng dấu gạch chéo ngược, nhưng dấu gạch chéo ngược sẽ được in cũng như XD Bash không dành cho người yếu tim :)
h4unt3r

@ h4unt3r: Lạ thật, đó không phải là kinh nghiệm của tôi. Đối với tôi, echo "Happy Birthday!"đầu ra 2 dòng. Đầu tiên là echo "Happy birthday"(không có câu cảm thán) và lần thứ hai là "Chúc mừng sinh nhật" (một lần nữa, không có câu cảm thán). Bạn có mở rộng lịch sử khi bạn thực hiện bài kiểm tra này không?
JWD

@jwd bạn đang chạy phiên bản bash nào? Tôi luôn luôn mở rộng lịch sử trên. Bạn đã vô tình sử dụng hai !! cho bài kiểm tra của bạn?
h4unt3r

@ h4unt3r : version 4.1.2(1)-release (x86_64-redhat-linux-gnu), chắc chắn chỉ có một người !đang được sử dụng. Tôi có histexpandmặt ở $SHELLOPTS. Tuy nhiên, tôi đã thử dùng 4.3,18 (2) trên một máy khác và nó hoạt động như bạn mô tả. Tôi đoán đó là một lỗi đã được sửa.
JWD

66

Tắt mở rộng lịch sử :

set +H

hoặc là

set +o histexpand

Bạn có thể thêm một trong những lệnh đó vào ~/.bashrcnếu bạn thường không sử dụng mở rộng lịch sử.

Bash 4.3 đã thêm một trường hợp đặc biệt :

ký tự mở rộng lịch sử cũng được coi là trích dẫn nếu nó ngay trước dấu ngoặc kép đóng trong chuỗi trích dẫn kép


Cảm ơn - điều này đã làm việc, nhưng tôi phải làm set +o histexpand, không phải set -o histexpand. Bạn có thể chỉnh sửa câu trả lời của bạn để khắc phục điều này?
Matthew

Rất tiếc, lỗi đánh máy, xin lỗi. Đã sửa.
Dennis Williamson

xuất sắc! đã tìm kiếm điều này cho AGES .... thx vm! vì thoát sẽ không hoạt động ... Tôi cũng không muốn sử dụng dấu ngoặc đơn ... Tôi sẽ thêm phần này vào .bashrcthx của tôi !!, không bao giờ được sử dụng !trong các tập lệnh và không có gì !! nó luôn luôn gặp rắc rối ...
Sức mạnh của Bảo Bình

Việc này thật là tuyệt! echo "@AquariusPower!"
joehanna

12

Sử dụng dấu ngoặc đơn (') thay vì dấu ngoặc kép ("). Dấu ngoặc đơn tắt tất cả các giải thích của nội dung trong đó, trong khi dấu ngoặc kép chỉ tắt một số.

bzr commit -m 'It works!'

4

Bây giờ tôi chỉ tìm thấy một cách khác, ít nhất sẽ hoạt động với echochuỗi ing (câu) mà bạn muốn chấm câu với dấu chấm than. Nó thực hiện một kết thúc chạy, nhiều hay ít, xung quanh biểu đồ Bash và chỉ mất một chút thời gian để viết mã.

Số hex cho một dấu chấm than, như được liệt kê trên http://www.ascii-code.com/ , là 21, vì vậy nếu bạn đặt \x21ở cuối chuỗi của mình echo -e $foo, hãy tạo $footiếng vang mở rộng của riêng nó [tức là foo=$(echo -e "$foo")], bạn sẽ làm gì nhận được khi bạn echo $foomột lần nữa là chuỗi có một !ở cuối. Và không có chuyển đổi lịch sử hoặc.

Hoạt động chắc chắn trong Bash 4+. Các phiên bản trước đó, ymmv.


Hmmm nó không làm việc cho tôi.
lzap

Tôi không hiểu những gì bạn đang nói về tiếng vang của chính nó. Diễn giải 'echo -e' và 'printf' đã thoát các mã bát phân, hex và Unicode. Trong trường hợp bạn đang sử dụng một trong hai thứ đó, bạn có thể sử dụng "\ 041" (bát phân cho "!") Hoặc "\ x21" (hex) để thay thế cho dấu chấm than. Ví dụ : printf "OMG\041". Nếu bạn đang xây dựng một chuỗi trích dẫn kép ở đâu đó không phải là echo hoặc printf, như chuỗi cam kết mà OP đã hỏi, bạn có thể nhúng $(echo -e "\041")vào chuỗi nơi có dấu chấm than. Như thế này : bzr commit -m "This is a great commit$(echo -e "\041")".
Todd Walton
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.