В скриптах отключено расширение истории?

9

Я понимаю, что следующая ошибка связана с !использованием для расширения истории:

$ echo "Hello!Tim"
bash: !Tim: event not found

Однако, если я помещаю команду в скрипт и запускаю скрипт, проблем нет:

$ cat myscript
echo "Hello!Tim"
$ bash myscript 
Hello!Tim

Это почему? В руководстве по bash упоминается причина?

Тим
источник
1
Хороший вопрос, просто сформулированный. Очень хорошо сделано!
Wildcard
Исходя из того, что я читаю здесь: gnu.org/software/bash/manual/html_node/History-Interaction.html Я считаю, что вам нужно использовать какой-то shoptмодификатор, чтобы заставить его работать в вашем скрипте. Я знаю, что это не совсем тот ответ, который вы ищете.
jesse_b
Какой вариант использования? Какой сценарий вы бы запустили, чтобы расширить вашу предыдущую историю? Или это расширит предыдущие команды из скрипта?
Джефф Шаллер
@JeffSchaller, числовое расширение истории в сценарии с положительными числами звучит как очень плохая идея, но я мог бы легко представить себе случаи использования для !!или !-2(отрицательные / относительные номера истории) или аналогичные. В большинстве случаев они будут решаться лучше другими способами, но это все еще хороший вопрос о том, как работает оболочка (и когда вам нужно / не нужно избегать восклицательных знаков!).
Wildcard

Ответы:

12

Да, расширение истории включено по умолчанию только для интерактивных оболочек.

Чтобы включить его для сценария оболочки, напишите:

set -H

Чтобы отключить его в интерактивной оболочке, напишите:

set +H

Чтобы определить, включено ли расширение истории в настоящее время, используйте некоторую форму следующего кода:

case $- in (*H*) echo enabled ;; (*) echo disabled ;; esac

Начав преподавать класс оболочки, я тщательно изучил руководство, чтобы выяснить, что такое «интерактивная оболочка». Это вопрос водоворота, поэтому позвольте мне избавить вас от некоторых неприятностей:

Оболочка имеет много вариантов. Некоторые из этих параметров инициализируются по-разному, когда оболочка имеет управляющий терминал (или когда запускается -i, бла-бла, как угодно, см. Ниже).

ВСЕ параметры оболочки могут быть изменены индивидуально.

«Интерактивная оболочка» - это обманчивый термин, когда вы пытаетесь определить его точно. Это действительно просто набор настроек параметров.

На вопрос о том, какие настройки делают оболочку интерактивной или нет, невозможно ответить; это становится смешным. Это точно такой же философский вопрос, как и Корабль Тесея .

Если вы запускаете интерактивную оболочку, но затем отключаете расширение истории, используете --noeditingфлаг, устанавливаете --norc, выключаете expand_aliasesи т. Д. И т. Д., То в каком смысле оболочка является интерактивной? Или когда он перестает быть интерактивным? Вы не можете ответить на эти вопросы.

Правда в том, что «интерактивный» - это просто удобный ярлык для набора различных опций оболочки. Точно так же "неинтерактивный". То же самое; просто набор поведений, каждый из которых может быть изменен индивидуально.

Итог: оболочка ведет себя по-разному, когда она запускается "в интерактивном режиме", и когда она запускается "неинтерактивно". Попытки точно определить эти термины после запуска глупо. Просто посмотрите на каждый отдельный вариант оболочки, чтобы понять ее поведение.


Я забыл, что в дополнение к собственному исследованию я подробно об этом писал на этом сайте.

Wildcard
источник
Спасибо. В руководстве я нахожу только «Эта опция включена по умолчанию для интерактивных оболочек» для set -H. Вероятно, вы делаете вывод, что «расширение истории включено по умолчанию только для интерактивных оболочек».
Тим
@ Тим, смотри остаток моего ответа. Это предложение руководства очень скользкое, и оно пытается найти ответ на вопрос "что такое интерактивная оболочка?" из man-страницы все равно что говорить по кругу. Это никуда не денется.
Wildcard
Что вы МОЖЕТЕ сказать, так это то, что следующий фрагмент кода всегда показывает, включено ли расширение истории в текущей оболочке:case $- in (*H*) echo enabled ;; (*) echo disabled ;; esac
Подстановочный
@ Тим, кстати, я понятия не имею, что ты имеешь в виду, что это мой "вывод", потому что это ясный смысл set -H. Это вариант Histexpand.
Wildcard
1
Я пробовал это на сценарии, и он не работал, пока я тоже не сделал set -o history, после проверки сset -o из скрипта, что он был отключен.
Даниэль С. Собрал