Запомните половинную команду, пока я проверяю

96

Я часто оказываюсь в следующей позиции: я начал вводить длинную команду в командной строке bash, но на полпути я обнаружил, что мне нужно проверить что-то с помощью другой команды. Это проблема, когда я на консоли (нет X), что часто бывает, потому что тогда у меня есть только следующие неудовлетворительные способы сделать это, о которых я знаю:

  • Нажмите ctrl+ alt+ F2и войдите в другую виртуальную консоль, найдите то, что я хотел, затем вернитесь и продолжите
  • ctrl+ a, введите echo + space+ enter, найдите то, что я хотел, нажимайте, пока не найдете мою команду, ctrl+ a, delx 5, ctrl+ eи продолжайте
  • Выделите то, что я до сих пор печатал, с помощью моей мыши (если gpm запущен, что обычно и происходит), нажмите ctrl+, cчтобы прервать, выясните, что я хотел, при этом стараясь не использовать мышь для выделения, затем нажмите среднюю кнопку мыши в новом окне и продолжить
  • Помолитесь богам командной строки, чтобы наполовину написанная команда не имела никаких побочных эффектов, а просто потерпела неудачу, и осторожно нажмите ввод, затем найдите то, что я хотел, нажимайте стрелку вверх, пока я не верну свою команду, и продолжайте
  • Запрыгивай в мою машину времени, путешествуй назад во времени и напоминай себе, чтобы начать экран, прежде чем начать вводить команду, вернуться в настоящее, нажать ctrl+ a c, узнать, что я хотел, нажать ctrl+ a ctrl+aи продолжить

Итак, я хочу знать, есть ли более элегантный способ сделать это? Этакая команда подобного типа или подобная?

Меня больше всего интересуют методы, которые не требуют какой-либо подготовки или настройки для работы.

Лауриц В. Таулов
источник

Ответы:

67

Несколько более быстрая версия alex's Ctrl + A Ctrl+ K(которая перемещается в начало строки и затем обрезает все вперед) состоит в том, чтобы просто использовать Ctrl+ U, который сокращает назад в bash, и всю строку (независимо от вашей текущей позиции) в zsh. Затем вы используете Ctrl+, Yчтобы вставить его снова

Михаил Мрозек
источник
1
Проверяя это, я делаю вывод, что Ctrl + U не перемещается назад и сокращается вперед, а наоборот, сокращается назад. Наличие курсора в середине команды оставляет все, что находится позади него в командной строке. Тем не менее, это решение на 33% лучше, чем решение @ alex, поскольку оно экономит время нажатия клавиш.
Lauritz V. Thaulow
2
@lazyr О, совершенно верно; на zshнем действительно разрезать всю линию, но на bashнем разрезает назад. Я никогда не замечал эту разницу раньше
Майкл Мрозек
2
О, я не знал, что Ctrl + U также помещает текст для уничтожения буфера. Приятно знать! :)
Alex
1
^U ^Kбудет иметь тот же эффект, что ^A ^Kи немного более эргономичный, и значительно более удобный под screen.
интуитивно
52

Выполните ctrl-A, чтобы перейти к началу строки, добавьте хеш и нажмите return - таким образом, он останется в истории команд в качестве комментария, и вы можете вернуться к нему с помощью курсора вверх.

РЕДАКТИРОВАТЬ: только что заметил, что это немного более элегантный вариант на вашем # 2;)

jamespo
источник
1
Да, и почему я не подумал об этом? Спасибо!
Лауриц В. Таулов
1
Мне нужно прочитать, прежде чем отправлять свой собственный ответ. У Джеймса все отлично.
Шон С.
4
Обратите внимание, что это не будет работать cshили zshпотому, что они не допускают комментарии в интерактивной оболочке. В zshнеобходимо активировать правильный вариант: setopt interactive_comments.
Сам Хочевар
1
@Sam Да, но ": команда" имеет тот же эффект (":" = нулевая команда)
barrycarter
6
@ barrycarter: нет, :для этой цели следует считать вредным и никогда, никогда не предлагать. Он будет выполнять все после точки с запятой, внутренних кавычек и т. Д. Со всеми связанными побочными эффектами.
Сэм Хочевар
29

Нажмите Ctrl+A, Ctrl+Kчтобы перейти к началу строки и удалить (убить) до ее конца. Затем проведите исследование, и когда будете готовы продолжить, нажмите Ctrl+Y(дергайте), чтобы вернуть сохраненную (убитую) строку назад.

Алекс
источник
3
Ах, теперь это больше похоже на то, что я имел в виду. И я делаю это все время в Emacs, должен был подумать о том же в командной строке.
Лауриц В. Таулов
13

В zsh я набираю Ctrl+, Zчтобы «приостановить» вводимую команду, и набираю другую команду. После того, как я выполнил эту команду (или прервал ее с помощью Ctrl+ C), приостановленная команда возвращается для редактирования (даже с запоминанием позиции курсора). В качестве дополнительного удобства, если командная строка пуста, когда я набираю Ctrl+ Z, клавиша bgвместо этого вызывает встроенную функцию (так что double Ctrl+ Zотправляет запущенную команду непосредственно в фоновый режим).

fancy-ctrl-z () {
  emulate -LR zsh
  if [[ $#BUFFER -eq 0 ]]; then
    bg
    zle redisplay
  else
    zle push-input
  fi
}
zle -N fancy-ctrl-z
bindkey '^Z'          fancy-ctrl-z

Я не знаю, как сделать что-то подобное в Bash.

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

жилль
источник
2
Ваша функция достойна восхищения, но знаете ли вы, что zshона уже встроена ? Он называется, push-lineи все, что вам нужно сделать, это использовать, bindkeyчтобы добраться до него.
Калеб
@Caleb: я не знаю, почему я использую, push-inputа не push-lineздесь, push-lineкажется более уместным (может быть, старые версии zsh были только push-input?). Но это не замена остальной части функции.
Жиль
Насколько я могу судить, единственная разница заключается в том же эффекте привязки к фоновому выполнению задания. Я что-то пропустил?
Калеб
1
@Caleb: Нет, просто я нахожу комбинацию двух одновременно удобной ( push-lineбесполезной в пустой строке, bgвключение Ctrl+Zполезно только в том случае, если я только что приостановил этот процесс с помощью Ctrl+Z) и мнемоники (я либо фоновый процесс или частичная командная строка).
Жиль
3
@Caleb push-inputприостанавливает весь входной буфер, тогда как push-lineприостанавливает только текущую строку. Если я набираю многострочную команду, я хочу приостановить всю команду, так push-inputчто это правильно. Я нахожу push-inputболее полезным, чем push-line(если я хочу отложить строку в многострочном входном буфере, я могу просто перейти к началу строки и вставить новую строку), так что я на самом деле удивляюсь, почему push-lineиспользуется связывание клавиш по умолчанию, а нет push-input.
Жиль
13

В bash просто введите Alt+ #.

Затем, когда вы будете готовы, нажмите Upзатем Alt+ #.

Первый помещает #в начало строки, чтобы превратить его в комментарий, затем принимает строку, как если бы вы нажали Enter.

Затем, когда вы делаете это во второй раз, он видит, что #в начале строки уже есть строка , поэтому он удаляет ее и принимает ее, снова сохраняя вам Enterключ.

Если второй раз просто вставляет другой #, вам нужно вместо этого набрать Alt+ - Alt+ #.

Вы можете заставить Zsh сделать то же самое, поставив

bindkey -M emacs '\e#' pound-insert

в вашем ~ / .zshrc.

Или, если вы используете привязки vi, вы можете печатать #из командного режима как в bash, так и в zsh.

Mikel
источник
2
У меня не работает, вторая команда, предназначенная для удаления #, просто добавляет больше # в начало.
Лауриц В. Таулов
1
Первый работает? Какую версию Bash вы используете?
Микель
3
Alt + # работает так, как вы описали в третьем абзаце, но не так, как в четвертом, он просто добавляет еще один # вперед и принимает строку. Я использую bash 4.1.5 (1) -релиз на Ubuntu 10.10.
Лауриц В. Таулов
1
О, дорогой, в bash требуется числовой аргумент, например, Esc+1затем Alt+ #для переключения.
Микель
Это работает, но гораздо более громоздко, чем просто Ctrl + A Del Ctrl + E, особенно в моей раскладке клавиатуры, где Alt + # на самом деле Alt + Shift + 3.
Лауриц В. Таулов
10

Одна из моих любимых функций zsh- встроенная функция push-line, которая позаботится об этом без каких-либо хакерских действий в других ответах здесь. У меня это связано с Ctrl+ lв моем .zshrcфайле, как это:

bindkey '^L' push-line

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

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

Калеб
источник
5
Привязан к Ctrl+Qи ESC qпо умолчанию (в режиме emacs).
Жиль
Есть ли что-то подобное для bash?
Магнус
@Magnus: Пожалуйста, просмотрите остальные ответы на этот вопрос. Есть решения для Bash, но не такие элегантные, как эта.
Калеб
@Caleb, я должен был быть более конкретным, есть ли подобная комбинация клавиш для bash?
Магнус
1
Это явно «правильный» ответ, для Zsh в любом случае! Я просто хочу упомянуть push-line-or-editвиджет, который по умолчанию не связан ни в одной раскладке. В подсказке верхнего уровня он делает то же самое push-line, но на любом уровне подсказки ниже он преобразует всю вводимую команду в многострочный буфер. Две замечательные функции на одной клавише! Я могу рекомендовать связывание push-line-or-editвместо простого push-line. Вы ничего не теряете и получаете полезную функциональность.
wjv
5

В дополнение к ctrl- a ctrl- kтрюку, если вы находитесь на экране, просто ctrl- a dотсоедините, затем присоединитеscreen -r

Вы также можете просто открыть другое окно с ctrl+a c

кроличий садок
источник
8
Если вы находитесь на экране, просто откройте другое окно с помощью Ctrl+A c.
Жиль
1
@ Жиль ... если вам не нужно использовать какой-либо аспект состояния оболочки (переменные, функции, псевдонимы и т. Д.).
интуитивно
4

Альтернативный способ, хотя и не идеальный, нажмите Ctrl-X Ctrl-E. Это откроет ваш редактор по умолчанию, содержащий вашу половинную команду. Затем вы можете сохранить вашу команду в файл или открыть новую оболочку из вашего редактора. Когда вы выходите из новой оболочки, она вернет вас в редактор, и сохранение содержимого автоматически выполнит их.

Это не идеально, потому что оно не возвращает вас к исходной оболочке, но либо заставляет выполнить команду, либо полностью ее отбрасывает. Но нет никаких временных выборок или буферов уничтожения, о которых нужно беспокоиться, а также есть несколько приятных настроек, например, если editor = vi

:wq            # execute the command
:cq            # cancel and abort
:! command     # execute command
:shell         # open a new shell
:r filename    # insert the contents of a file for editing
:r ! command   # insert the output of a command for editing
forcefsck
источник
Очень хорошая альтернатива. Я vi-emacs-agnostic, так что я буду счастлив, как моллюск, использующий это, когда действительно нужны powertools. (.. Говоря о VI, я попробовал Линукс эмулятор N64 Mupen64Plus некоторое время назад Esc завершает работу эмулятора без сохранения я вскоре отказался играть что - нибудь.)
Lauritz В. Thaulow
1
@lazyr, для Debian / Ubuntu запустите sudo update-alternatives --config editorи выберите ваш любимый редактор. Для других систем установите переменные окружения EDITOR или VISUAL для вашего любимого редактора, например, добавьте export EDITOR=/usr/bin/nanoв ваш .bashrc.
forcefsck
3

Подобно методу добавления #в начале строки, есть, пожалуй, более простой метод, который я использую, который не требует возврата к началу строки:

Просто добавьте открытую цитату и не закрывайте ее, одинарную или двойную.

Затем нажмите Enter.

Затем нажмите CtrlC.

Частичная команда сохраняется в истории команд (доступно через стрелку вверх), но фактически не выполняется.

Wildcard
источник
2

Используя zsh, если вы наберете <ESC> q(escape, затем Q), строка вашего приглашения будет обрезана, чтобы вы могли ввести другую команду. Вы автоматически получите обратно вырезанный текст в следующем приглашении.

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

Это не самый эффективный способ, если вам нужно использовать несколько команд для проверки / подготовки (вам придется перепечатывать <ESC> qперед каждой командой). Но я думаю, что это можно привязать к более короткому ярлыку.


Если вы просто хотите проверить руководство, наберите <ESC> h(escape, затем H). Это запустит run-helpвстроенное, с первым словом командной строки в качестве аргумента. Вы найдете обратно свою линию нетронутой, как только закончите.

loxaxs
источник
Большинство терминалов позволит вам сделать M-qвместо<ESC> q
sleblanc