Просто интересно, почему это не работает
#!/bin/bash
ls /bin
ls !$
Я рассчитываю запустить ls /bin
дважды, но второй вызывает ошибки, так как !$
не был интерпретирован
Я что-то пропустил или !$
работал только в командной строке?
Я не мог найти соответствующую часть в man bash
(на Mac)
Ответы:
Расширение истории и истории отключено по умолчанию, когда оболочка работает не в интерактивном режиме.
Тебе нужно:
или же:
это повлияет на все экземпляры bash, которые
script.sh
могут работать.источник
bash
что выполняетсяscript.sh
, но также и на все другиеbash
экземпляры, которыеscript.sh
могут в конечном итоге выполняться (как и другиеbash
сценарии ...).bash
экземпляр, который запускает ваш скрипт.Нормальной вещью было бы
или
или
Предостережения: стоит помнить, что у каждого из них есть свои подводные камни. Решение $ _ захватывает только последний единственный аргумент: так
ls foo bar
что оставим $ _, содержащий justbar
. Тот, который используетset
, переопределит аргументы ($1
,$2
и т. Д.). И все это, как написано, будет работать, но при обобщении на более сложные команды (где экранирование и пробелы имеют значение), вы можете столкнуться с некоторыми трудностями. Например:ls 'foo bar'
(где один аргумент pathnamefoo bar
содержит два или более пробелов или любые другие пробельные символы) не будет работать правильно ни в одном из этих примеров. Для обхода этих случаев может потребоваться правильное экранирование (возможно, в сочетании сeval
командой) или использование"$@"
вместо$*
.источник
$_
Способ не является портативным, вы правы.set
Подход работает в неинтерактивном тире, и с${1+"$@"}
(плюс ЗШ глобального псевдонима) трюк должна быть общим, хотя я смутно помню , чтоset
есть история , не будучи совершенно портативным с некоторыми (старыми?) Оболочками.eval
Насколько я знаю, подход define-a-variable-holding-the-command-and-then-eval-it, особенно с использованием правильного экранирования и фактической команды, в целом переносим.