В bash, как мне избежать восклицательного знака?


183

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


1
Работаю bzr commit -m "It works"!тоже.
kba

1
Как я уже отмечал ранее, команда, которую вы вводите, действительно работает сама по себе :)bzr commit -m "It works!"
h4unt3r

Еще более причудливый случай с вложенными кавычками: stackoverflow.com/questions/22125658/…
Сиро Сантилли 新疆 改造 中心 法轮功 六四 事件

1
Хотя принятый ответ является хорошим решением для ваших проблем с фиксацией, я чувствую, что это не ответ на актуальную проблему: расширение истории Bash . Пожалуйста, рассмотрите возможность принять ответ Дениса?
Арьян

Ответы:


153

Поскольку вы не зависите от bash для расширения переменных в сообщении фиксации, вы можете вместо этого использовать одинарные кавычки. Строки в одинарных кавычках не раскрываются с помощью bash.

bzr commit -m 'This does work!' 

24
Поскольку вопрос был "Как мне избежать восклицательного знака?" а не "Как не развернуть восклицательный знак?" Я не думаю, что это действительно. В некоторых случаях (например, при передаче апострофов и восклицательных знаков в одной командной строке) это не работает. Ответ ниже работает намного лучше, чтобы делать то, что нужно многим людям.
Янв

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

туш! Это была конкретная проблема. Я просто хочу, чтобы ответ на мои вопросы можно было использовать во многих ситуациях. pS: причина, по которой я даже упомянул это, была в том, что мне нужно было передать апостроф и восклицательный знак в perl-программу, и мне нужно следующее решение. :)
Янв

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

153

Вот другой метод, если вы хотите двойные кавычки, а также восклицательный знак:

echo "It's broken"'!'

Это работает, даже если !это не в конце строки.

Например:

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

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


4
Хороший совет, JWD. Я не понимал, что строки bash можно объединять, просто пропуская пробелы между ними.
Алан Х.

На самом деле, если восклицательный знак находится в конце строки, в которой вы находитесь, 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 .... THM VM! как escape не сработает ... Я тоже не хочу использовать одинарные кавычки ... Я добавлю это к своему .bashrcthx !!, никогда не использовавшемуся !в скриптах и ​​ни за что !! это всегда беспокоило ...
Сила Водолея

Это так круто! echo "@AquariusPower!"
Джоанна

12

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

bzr commit -m 'It works!'

4

Я только что нашел другой способ, который будет по крайней мере работать со echoстроками (предложениями), которые вы хотите акцентировать восклицательным знаком. Он выполняет более или менее конечный прогон вокруг своей вершины Bash и занимает чуть больше времени для кодирования.

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

Работает наверняка в Bash 4+. Более ранние версии, ymmv.


Хм, это не работает для меня.
lzap

Я не понимаю, что вы говорите о повторении себя. 'echo -e' и 'printf' интерпретируют экранированные восьмеричные, шестнадцатеричные и юникод-коды. В случаях, когда вы используете любой из них, вы можете использовать «\ 041» (восьмеричное для «!») Или «\ x21» (шестнадцатеричное) для замены восклицательного знака. Например: printf "OMG\041". Если вы строите строку в двойных кавычках где-то, которая не является echo или printf, как об этом спрашивала OP строка коммита, вы можете вставить $(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.