Як уникнути знака оклику в бешкеті?


183

Я хочу зробити щось подібне bzr commit -m "It works!". Я можу втекти від оклику, роблячи це bzr commit -m "It works\!". Однак тоді моє повідомлення про фіксацію включає зворотну косу рису. Як я уникаю знака оклику, ігноруючи зворотній косу рису?


1
Робити bzr commit -m "It works"!роботи теж.
кба

1
Як я вже зазначав перед командою, яку ви кладете, насправді вона працює самостійно :)bzr commit -m "It works!"
h4unt3r

Навіть quirkier випадок з вкладеними лапками: stackoverflow.com/questions/22125658 / ...
Чіро Сантіллі新疆改造中心法轮功六四事件

1
Хоча прийнята відповідь є гарним вирішенням ваших проблем із зобов'язаннями, я вважаю, що це не відповідь на власне питання: Розширення історії Баша . Будь ласка, подумайте про прийняття відповіді Денніса?
Ар'ян

Відповіді:


153

Оскільки ви не залежите від bash для розширення змінних у вашому повідомленні, ви можете замість цього використовувати окремі лапки. Рядки в одиничних лапках не розширюються bash.

bzr commit -m 'This does work!' 

24
Оскільки питання було "Як я ухиляюся від оклику?" а не "Як мені не розгорнути знак оклику?" Я не думаю, що це справедливо. Інколи (наприклад, при передачі апострофів та знаків оклику в одному командному рядку) це не працює. Відповідь нижче працює набагато краще, щоб зробити те, що потрібно багатьом людям.
Янн

7
@Jann: Ви на 100% маєте право на це, але я думаю, що тут виникає стільки запитань щодо суперпользователя: чи ми відповімо на це питання, чи ми допомагаємо людям вирішити їх конкретну проблему. Я думаю, що обидва способи можуть бути корисними, і це було шукати допомоги з конкретного питання.
Бенджамін Баньє

touché! Це було конкретне питання. Я просто прагну, щоб відповідь на мої запитання могла використовуватись у багатьох ситуаціях. pS: Причиною, про яку я навіть згадував, було те, що мені потрібно було передавати як апостроф, так і знак оклику в програму perl, і мені було потрібно наступне рішення. :)
Янн

Я погоджуюся і з Бенджаміном, і з Дженном, але дав протизаконні відгуки. Назва питання індексується пошуковими системами, і ось я прийшов сюди, і, мабуть, більшість користувачів сюди приїжджає. Тому я вважаю, що важливо, щоб актуальне питання відображало проблему, що стоїть за ним. На інших форумах людей рекомендують (майже змушені) запитувати, що саме вони шукають. Відповіді на погано висловлені запитання підтримують неохайність, і саме це є причиною мого протистояння. Як компроміс / рішення, моя пропозиція - допомогти адаптувати заголовок, щоб він відображав фактичну проблему.
ChristophK

153

Ось ще один метод, якщо ви хочете подвійні лапки, а також вигук:

echo "It's broken"'!'

Це працює, навіть якщо значення !не знаходиться в кінці рядка.

Наприклад:

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

Бонус: Подібну техніку можна використовувати для втечі будь-якого тексту в Sh або Bash (за допомогою sed): див. Перший варіант у цій відповіді . Крім того, якщо ви bash-completionвстановили, ви , ймовірно , є функція доступна вже.quote()


4
Гарна порада, JWD. Я не знав, що струни башу можна об'єднати, просто опустивши пробіл між ними.
Алан Г.

Насправді, якщо знак оклику знаходиться в кінці рядка, на якому ви чітко, echo "Happy birthday!"буде працювати так, як очікувалося, інакше ви зможете уникнути його із зворотним косою рисою, але зворотний штрих також буде надрукований, а XD Bash не для слабкого серця :)
h4unt3r

@ h4unt3r: Дивно, це не мій досвід. Для мене echo "Happy Birthday!"виводить 2 рядки. Перший - це echo "Happy birthday"(без вигуків), а другий - «З днем ​​народження» (знову ж ніякого вигуку). Чи увімкнено розширення історії, коли ви робите цей тест?
jwd

@jwd, яку версію bash ти працюєш? У мене завжди є розширення історії. Ви випадково використали двох !! для вашого тесту?
h4unt3r

@ h4unt3r:, version 4.1.2(1)-release (x86_64-redhat-linux-gnu)безумовно, використовується лише один !. Я histexpandприсутні в $SHELLOPTS. Однак я просто спробував випустити 4.3.18 (2) на іншій машині, і він поводиться так, як ви описали. Я здогадуюсь, це була помилка, яку виправили.
jwd

66

Вимкнення розширення історії :

set +H

або

set +o histexpand

Ви можете додати до своєї команди одну з цих команд, ~/.bashrcякщо зазвичай не використовуєте розширення історії.

Bash 4.3 додав окремий випадок :

Характер розширення історії також трактується як цитований, якщо він негайно передує заключній подвійній цитаті у рядку з подвійним котируванням


Спасибі - це спрацювало, але мені довелося це зробити set +o histexpand, ні set -o histexpand. Чи можете ви відредагувати свою відповідь, щоб виправити це?
Метью

На жаль, помилково, вибачте. Виправлено.
Денніс Вільямсон

видатний! шукав це для AGES .... thx vm! як уникнути роботи звичної ... Я також не хочу використовувати окремі цитати ... Я додам це до свого .bashrcTHX !!, ніколи не використовуваного !в сценаріях і дарма !! це завжди хвилювало ...
Сила Водолія

Це так приголомшливо! echo "@AquariusPower!"
joehanna

12

Використовуйте одинарні лапки (') замість подвійних лапок ("). Одномісні цитати вимикають всю інтерпретацію матеріалів у них, тоді як подвійні лапки відключають лише деякі.

bzr commit -m 'It works!'

4

Щойно я знайшов інший спосіб, який, принаймні, буде працювати з echoрядками (реченнями), які ви хочете розділити на знак оклику. Кінцевий запуск, більш-менш, навколо Bash histexpand і займає лише трохи більше часу, щоб кодувати.

Шестнадцятковий знак оклику, як зазначено на http://www.ascii-code.com/ , дорівнює 21, тож якщо ви поставите \x21в кінці рядка echo -e $foo, зробіть $fooвласне розширене відлуння [тобто, foo=$(echo -e "$foo")], що ви отримати, коли ви echo $fooзнову - це рядок з а !в кінці. І жодного перемикання йогосторонніх шир.

Працює точно в Bash 4+. Більш ранні версії, мммв.


Хммм, це не працює для мене.
lzap

Я не розумію, що ви говорите про відлуння самого себе. 'echo -e' і 'printf' інтерпретують уникнулі восьмеричні, шістнадцяткові та Unicode коди. У випадках, коли ви використовуєте будь-який із цих, ви можете використовувати "\ 041" (вісімку для "!") Або "\ x21" (шістнадцяткову), щоб увімкнути знак оклику. Наприклад: printf "OMG\041". Якщо ви будуєте рядок з подвійним цитуванням десь не є відлунком або printf, як, наприклад, запит рядка ОП, про який ви питали, ви можете вставити $(echo -e "\041")в рядок, де має бути знак оклику. Як це: bzr commit -m "This is a great commit$(echo -e "\041")".
Тодд Уолтон
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.