Как выполнить последовательные команды из истории?


49

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

$ !432; !433; !434; !435

Мне любопытно, есть ли более эффективный способ сделать это?


1
Не публиковать это как ответ, потому что он не выполняет команды, но вы можете history -p \!43{2..5}напечатать команды 432 - 435 на терминал, пригодные для последующего копирования / вставки.
Уайлдкарт

Ответы:


48

Если это относится к командам, запущенным совсем недавно, более эффективный способ - ссылаться на них с отрицательными числами:

!-4; !-3; !-2; !-1

Кроме того, как только вы это сделаете, ваша последняя запись истории будет содержать всю цепочку команд, так что вы можете повторить это с !!.


Изменить: Если вы еще не сделали, познакомьтесь с великолепной встроенной функцией fc, упомянутой Жилем . (Используйте help fc.) Оказывается, вы также можете использовать отрицательные числа с ним, так что вы могли бы сделать то же, что и выше, используя

eval "`fc -ln -4 -1`"

Это имеет одно предостережение: после этого evalстрока сохраняется в истории как последняя команда. Так что если вы запустите это снова, вы попадете в петлю!

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

 fc -4 -1

Вы можете даже изменить порядок диапазона команд: fc -1 -4


Я только что прочитал, что я написал ... LOL. На самом деле, я не уверен насчет reinvoke ( reinvoke может быть?), Но спасибо за рассказывать :) Я всегда ценю корректировки.
rozcietrzewiacz

Scrabblefinder.com говорит, что повторный вызов - верное слово Scrabble. Не может быть более определенным, чем это. :)
BentFX

1
С таким хорошим ответом (+1) не имеет значения, как вы его пишете; тем более, что ни одна из орфографических форм не отображается в трех основных английских словарях: Оксфорд, Кэмбридж, Мерриам-Вебстер (я бы
выбрал

34

Для просмотра ряда команд в истории используйте встроенную fcкоманду:

fc -ln 432 435

Чтобы выполнить их снова:

eval "$(fc -ln 432 435)"

4
Очень хорошо. Мне любопытно, почему man fcничего мне не дает. Что означает fc? Какие еще есть варианты?
Эрик Уилсон,

2
@Eric Wilson ... type help fc... а также help help.... help: help [-dms] [pattern ...] Отображение информации о встроенных командах.
Peter.O

Я только что вернулся сюда в поисках вашего ответа. Это действительно отличный встроенный! Особенно, когда вы используете его функциональность по умолчанию - вызывая редактор для изменения диапазона команд для воспроизведения. Спасибо, Жиль.
rozcietrzewiacz

1
Без -lфлага он будет казнен без зла eval.
Бернхард

1
@EricWilson Поиск в Google привел меня к книге «Unix in Nutshell», в которой говорится fc«найти команду» или «исправить команду».
Ленивец

10

Существует хороший и альтернативный способ последовательного запуска ряда команд из истории Bash:
вместо использования заменителя истории ( !432или !-4), вы можете искать в истории с помощью Ctrl+ r, и как только вы найдете первую команду, которую хотите запустить, нажать Ctrl+ o( оперировать и получить далее ) вместо returnклавиши.
Это запустит команду и предложит следующую из истории. Вы можете нажать Ctrl+oстолько раз, сколько пожелаете, и завершить последовательность либо returnпоследней, либо Ctrl+cостановиться, не запуская ее.


Хм, после того, как я нажму, Ctrl-oон просто выводит литерал ^oи ломает мой (reverse-i-search). Может быть, есть и другие настройки.
Сиро Сантилли 新疆 改造 中心 法轮功 六四 事件

8

Чтобы выполнить команды немедленно, а не редактировать их, вот синтаксически более тонкая версия ответа Джайлса с использованием eval :

fc -e: 432 435

Аргумент двоеточия для -e - это nash bash, который пропускает шаг «открыть в редакторе», который хочет fc. Кроме того, теперь (недавняя) история будет содержать фактические команды из истории, а не оператор eval.


0

fc для цикла и xsel

Это хорошо работает, когда я хочу объединить и повторно запустить последние n команд несколько раз:

fcn() (
  from="${1:-2}"
  to="${2:-1}"
  if [ "$from" -ne "$to" ]; then
    for i in `seq "$from" -1 "$(($to + 1))"`; do
      printf "$(fc -ln -${i} -${i}) && "
    done
  fi
  printf "$(fc -ln -${to} -${to})"
)

Затем:

$ echo a
a
$ echo b
b
$ echo c
c
$ fcn 3 1 | xsel -b
$ # Paste.
$  echo a &&  echo b &&  echo c
a
b
c
$ # Paste again if you feel like it.
$  echo a &&  echo b &&  echo c
a
b
c

Или для больших команд, которые могут нуждаться в некотором редактировании:

fcn 3 1 >cmds.sh
vi cmds.sh
bash cmds.sh
bash cmds.sh
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.