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

44

Я бы хотел немного улучшить свой рабочий процесс с помощью Bash, и я понимаю, что часто хочу выполнить одну и ту же команду для другого исполняемого файла.

Некоторые примеры:

Git (где я хотел бы быстро изменить второе слово):

git diff     foo/bar.c
git checkout foo/bar.c

Cat / rm (где нужно изменить только первое слово):

cat foo/is/a/very/long/path/to/bar.c
rm  foo/is/a/very/long/path/to/bar.c

Я знаю , что могу ударить Ctrl+ aто , Delчтобы удалить первое слово, но мне интересно , если есть более быстрый способ сделать это.

nowox
источник
Честно говоря, я думаю, что безопаснее всего использовать Ctrl + a и удалить. Это определенно не очень медленно.
agweber

Ответы:

56

!$ расширяется до последнего слова вашей предыдущей команды.

Так что вы могли бы сделать:

cat foo/is/a/very/long/path/to/bar.c

rm !$

или:

git diff foo/bar.c

git checkout !$

Ваши примеры случайно повторяли только последнее слово, поэтому !$работали нормально. Если у вас действительно было много аргументов, которые вы хотели бы повторить, и вы просто хотели изменить первое слово, вы можете использовать его !*, который распространяется на все слова предыдущей команды, кроме нуля.

См. Раздел «РАСШИРЕНИЕ ИСТОРИИ» справочной bashстраницы. Там много гибкости.

Spiff
источник
16
Правильно и правильно. Я хотел бы только поставить предупреждение : у !$вас нет полного визуального контроля над линией, которую вы запускаете . Это может иногда привести к вредным последствиям. Особенно, если вы попали в опечатку. Требуется от того, historyчто расширить. Так что если вы напишите последнюю команду с пробелом в начале, вероятно, эта команда не завершится в истории. При выполнении вашей новой команды с !$оболочкой параметры не будут приниматься из последней набранной командной строки, а только из последней истории. Здесь же больше слов.
Хастур
1
@Hastur Вы можете настроить свою оболочку для расширения истории на вкладке или после ввода, чтобы предотвратить несчастные случаи.
slhck
2
@Hastur, поэтому вам нужно дважды нажать вступление в zsh (бесстыдное продвижение)
Брайам
@Hastur - Когда у меня возникают сомнения по поводу того, что произойдет, или я запоздало осознаю, что мне нужно сначала сделать что-то еще, прежде чем запускать что-то длинное, что я только что набрал, я перехожу к началу строки и добавляю #или, echo чтобы я мог Посмотрите на это, и оно войдет в историю, так что я могу вернуть его обратно и запустить снова без отключения префикса.
Джо
28

Ctrl+ aперейти в начало строки, затем Alt+, dчтобы удалить первое слово.

jjlin
источник
9
Сокращение слова удаления на самом деле Meta + d, и Meta обычно отображается на Alt на компьютерах с Linux. На платформах, где это не так, альтернативой для получения модификатора Meta является использование Escape в качестве префикса. См en.wikipedia.org/wiki/Meta_key
Густаво Giraldez
2
@ GustavoGiráldez, если вы хотите углубиться, то Meta+Dдействует только если emacsон включен ( set -o emacsпо умолчанию или просто). Он не будет работать в низкоуровневом редакторе или emacsотключен.
TC1
Во многих терминалах (потому что это терминальная вещь, а не Bash), ключ home также будет идти в начало строки. Многие ноутбуки сопоставляют Fn + Left с ключом дома. Точно так же клавиша конца обычно идет в конец строки. Я еще не использовал эмулятор терминала, который не поддерживает эти горячие клавиши.
Kat
1
@Mike С другой стороны, C-aи M-dгораздо быстрее печатать, если ваши руки уже находятся в положении для печати.
jjlin
@Майк, это что-то плохое. Введите catи сравните то, что вы получите, нажав Home ( ^[[Hздесь) и нажав Ctrl + a ( ^A).
Йонас Шефер
17

Я не уверен, будет ли это на самом деле быстрее или нет, но посмотрите эту статью, особенно пункт # .3:

  1. Замените строку из предыдущей команды, используя ^ str1 ^ str2 ^

В следующем примере сначала мы выполнили команду ls для проверки файла. Позже мы поняли, что хотим просмотреть содержимое файла. Вместо того, чтобы снова вводить полное имя файла, мы можем просто заменить «ls» в предыдущей команде на «cat», как показано ниже.

$ ls /etc/cron.daily/logrotate

$ ^ls^cat^
cat /etc/cron.daily/logrotate
Benguin
источник
15

Alt+.

Если вам нужно только повторить последнюю часть одной из предыдущих команд, вы можете использовать Alt+ ., чтобы вставить последний аргумент, взятый из последней строки истории.

При нажатии более одного раза будет заменено то, что было вставлено с последним аргументом строки перед ...

Например, если последние 2 команды были:

cat foo/is/a/very/long/path/to/bar.c
pico foo/is/a/very/long/path/to/SomeWhereElse.c

В оболочке пишу rmи жму Alt+ .появится:

rm foo/is/a/very/long/path/to/SomeWhereElse.c

если я нажму снова Alt+ .он появится вместо

rm foo/is/a/very/long/path/to/bar.c

и так далее...

Hastur
источник
Не знаю почему, но это не работает на моей консоли Mac.
Лулалала
Здесь есть сочетания клавиш , с которыми известно работать bash. Кстати, вы уверены, что вы используете Bash в качестве оболочки ?
Хастур
1
Я думаю, что это вещь Mac. Когда я
печатаю
12

В дополнение к ответу @jjlin вас могут заинтересовать следующие советы:

  • Ctrl+ wудаляет слово слева от вас
  • Ctrl+ kудаляет от курсора до конца командной строки
  • Ctrl+ uудаляет из курсора в начало командной строки
  • Alt+ bперемещает курсор на одно слово назад
  • Alt+ fперемещает курсор на одно слово вперед
  • $_ содержит последний аргумент предыдущей командной строки

Подробнее об этом смотрите в разделе «Имена команд Readline» на bashстранице руководства .

например:

cat foo/is/a/very/long/path/to/bar.c
rm $_
maiki
источник
Это хорошие советы, но они не отвечают на вопрос.
Slhck
@slhck ИМХО, потому что заголовок вопроса не соответствует приведенным примерам. Если мы сосредоточимся на примерах, как я сделал, заголовок должен быть «Как быстро изменить слово в команде bash?» , Вот почему мой ответ "в дополнение к ответу @jjlin". Но я думаю, что вопрос должен быть уточнен.
Май
ОП всегда хочет удалить (обменять) первые nслова в команде, причем n = 1в первом примере и n = 2во втором. Ответ jjlin показывает, как удалить первое слово (и, повторно применив ярлык, удалить до nслов). В вашем ответе перечислено несколько сочетаний клавиш Bash (которые действительно полезны), но ни один из них не является эффективным способом удаления первых nслов.
Slhck
Хм, читая еще раз, $_параметр, вероятно, сработает, если будет только один аргумент (т. Е. n = m - 1Где mобщее количество аргументов). Остальная часть ярлыков не имеет отношения к вопросу, хотя.
Slhck
@slhck Ради спора я прочитал первый пример как «
замени
8

Если вы хорошо владеете vi, вы можете активировать привязки vi в bash (большинство оболочек?) С помощью команды set -o vi. Затем вы можете использовать обычные клавиши vi для редактирования вашей команды. В первом примере вы можете ^wcwудалить «diff», а затем изменить его на checkout.

Возможно, не стоит изучать сочетания клавиш vi просто для редактирования командной строки, но если вы их уже знаете, это будет аккуратное повышение производительности.

Chaosed0
источник
Я узнал о kornshell, так set -o viбыло, как я жил! Я даже делаю это в своих подсказках bash.
bgStack15
bindkey -vдля зш. Esc 0 c w
user530873
6

Есть много способов снять шкуру с этой кошки!

Чтобы заменить определенную строку, ^old^new^extraбудет принимать вашу предыдущую команду, замените oldс new, и присоединять extra. Вы можете остановиться как угодно; Например ^old, заменит oldпустую строку и добавит пустую строку (по сути, удаляя oldи больше ничего не делая).

1. ^diff^checkout
2. ^cat^rm

Особенно полезный вариант этого:

for i in `seq 1 10`; do echo something complicated; done
# inspect the output to see if it looks right
^echo

Чтобы заменить определенное слово, вы можете использовать !m:n-pдля ссылки на слова nчерез pкоманду m(используйте отрицательные числа для обратного отсчета от текущей команды). Вы можете опустить -pчасть, чтобы ссылаться на одно слово, и опустить :m-pчасть, чтобы сослаться на всю команду. Специальные формы !!для !-1, !$для последнего слова предыдущей команды, и !*для аргументов (все , кроме слов 0) из предыдущей команды довольно удобно.

1. !!:0 checkout !!:2-
2. rm !*

Я часто использую оба из них; zsh особенно хорош здесь, поскольку нажатие на вкладку раскроет загадочные вещи, чтобы убедиться, что вы правильно поняли.

Есть также так много способов сделать это с редактированием строки. Читайте о сочетаниях клавиш вашей оболочки.

Даниэль Вагнер
источник
-2

Большинство терминальных программ поддерживают ...

  • Нажмите по <Up-Arrow>мере необходимости, чтобы снова отобразить одну из предыдущих командных строк из истории.
    • Нажмите <Down-Arrow>при необходимости, чтобы перейти к списку истории.
  • Нажмите по <Left-Arrow>мере необходимости, чтобы переместить курсор в конец второго слова.
  • Нажмите <Backspace>при необходимости, чтобы стереть второе слово.
  • Введите замену второго слова.
    • Нажмите <Right-Arrow>/ <Left-Arrow>при необходимости, чтобы изменить положение для получения дополнительных изменений.
  • Нажмите, <RETURN>чтобы выполнить команду

Если нужная вам командная строка была не последней, выполните поиск в обратном направлении, <Ctrl-r>как описано в вопросе ...
Есть ли способ использовать ctrl-r после ввода части команды в bash?
Затем отредактируйте с помощью клавиш со стрелками по мере необходимости.

DocSalvager
источник
-3

Что я делаю (Ubuntu / Bash):

1) Arrow upэй, чтобы вернуть предыдущую команду.
2) Homeключ, чтобы вернуться в начало.
3) Изменить команду при необходимости.

Защита от дурака и особенно полезна для многострочных команд.

Vorac
источник