Существует ли ярлык для выполнения серии команд в истории Bash?

20

Предположим, у меня есть следующий тривиальный пример в моем history:

...
76 cd ~
77 ./generator.sh out.file
78 cp out.file ~/out/
79 ./out/cleaner.sh .
80 ls -alnh /out
...

Если я хотел выполнить команды 77, 78и 79в одной команде, существует ли ярлык для этого? Я пытался !77 !78 !79, который просто поместит их все в одну строку для выполнения.

MrDuk
источник
9
Все в !77 ; !78 ; !79порядке?
thrig
1
Я предполагаю, что что- либо, кроме ввода построчно, в порядке, но надеялся на что-то более краткое (по линии !77-79)
MrDuk
1
@MrDuk, парень, мне понадобилось время, чтобы вспомнить. Смотрите мой обновленный ответ для очень краткого решения! :)
Wildcard
Это волшебно! :)
MrDuk

Ответы:

28

РЕДАКТИРОВАТЬ: Вы можете сделать это POSIX-совместимым способом с помощью инструмента исправленияfc :

fc 77 79

Это откроет ваш редактор (вероятно vi) с командами с 77 по 79 в буфере. При сохранении и выходе ( :x) команды будут запущены.


Если вы не хотите их редактировать и вы ОЧЕНЬ уверены, что знаете, какие команды вы вызываете, вы можете использовать:

fc -e true 77 79

Он используется trueв качестве «редактора» для редактирования команд, поэтому он просто завершает работу без внесения каких-либо изменений, и команды запускаются как есть.


ОРИГИНАЛЬНЫЙ ОТВЕТ:

Вы можете использовать:

history -p \!{77..79} | bash

Это предполагает, что вы не используете псевдонимы или функции или какие-либо переменные, которые присутствуют только в текущей среде выполнения, поскольку, конечно, они не будут доступны в новой запускаемой оболочке.


Лучшее решение (спасибо Майклу Хоффману за напоминание в комментариях):

eval "$(history -p \!{77..79})"

Один из очень, очень немногих случаев, когда evalэто действительно уместно!


Также см:

Wildcard
источник
2
Это не будет работать правильно, если какая-либо из команд изменит текущую среду выполнения, например, путем изменения переменной или выполнения операции a cd, но это крайний случай.
G-Man говорит «Восстановить Монику»
3
eval "$(history -p \!{77..79})"должно сработать.
Майкл Хоффман,
1
@MichaelHoffman, я думал об этом и думал, что попробовал это, но я только понял, что я оставил цитату! D'о! Не удивительно, что это не сработало ... редактирование ответа сейчас.
Wildcard
14

Простой ответ: вместо того , чтобы !77 !78 !79,

  • наберите, !77; !78; !79чтобы сделать то, что вы пытаетесь сделать - выполните команду 77, затем команду 78, а затем команду 79, безусловно, или
  • введите !77 && !78 && !79 команду 77 и проверьте, успешно ли она выполнена. И затем, если команда 77 выполнена успешно, выполните команду 78. И затем, если команда 78 прошла успешно, выполните команду 79.

Немного умнее ответ (если вы находитесь в окне типа терминала):

  • Выясните, какой номер команды будет следующей введенной вами командой.
    • Это можно включить в вашу подсказку; Я верю, что это в том числе \!в вашем PS1.
    • Или посмотрите на свой список истории. Если последняя запись 82 history, то ваша следующая команда - 83.
  • Вычтите 83−77 = 6.
  • Тип !-6. Это повторно выполнит команду 77.
  • Выберите !-6, скопируйте и вставьте его. Поскольку ваше повторное выполнение команды 77 ( ./generator.sh) было командой 83, теперь вы выполняете команду 84, поэтому !-6повторите команду 78.
  • Повторите вставку !-6по желанию.
G-Man говорит: «Восстанови Монику»
источник