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

10

Иногда я работаю над новым (ubuntu) окном, и я gitпечатаю и получаю предупреждение:

The program 'git' is currently not installed.  You can install it by typing:
apt-get install git-core

Если это произойдет, я знаю, что могу взять последнюю строку, выполнив что-то вроде:

!! 2>&1 | tail -n 1

Но как я могу выполнить результат этого ( apt-get install git-core) наиболее легко?

Я понимаю, что мог сделать

`!! 2>&1 | tail -n 1`

но есть ли способ на самом деле передать вывод и запустить его? Это не похоже на работу:

!! 2>&1 | tail -n 1 | sh

Кроме того, эта 2>&1часть немного громоздка, поэтому мне было бы любопытно, если есть более простой способ сделать это тоже.

редактировать

Также было бы приемлемо как-то сохранить это в переменную, а затем выполнить переменную:

!! 2>&1 | tail -n 1 | (store as $mycmd)
$mycmd

Но я не уверен, что знаю способ передачи stdoutв переменную, по крайней мере, с переменной, находящейся справа от команды.

УХО
источник

Ответы:

8

Когда вы набираете команду, которой нет в вашей системе, bash запускает функцию command_not_found_handle(). В этой функции есть вызов /usr/lib/command-not-foundскрипта, который печатает сообщения.

Ubuntu 12.04

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

Если вы экспортируете переменную, COMMAND_NOT_FOUND_INSTALL_PROMPTвам будет предложено установить отсутствующий пакет:

pbm@ubuntu:~$ git
The program 'git' is currently not installed.  You can install it by typing:
sudo apt-get install git
pbm@ubuntu:~$ export COMMAND_NOT_FOUND_INSTALL_PROMPT=""
pbm@ubuntu:~$ git
The program 'git' is currently not installed.  You can install it by typing:
sudo apt-get install git
Do you want to install it? (N/y)y
sudo apt-get install git
[sudo] password for pbm: 

Старые версии Ubuntu

К сожалению, нет, COMMAND_NOT_FOUND_INSTALL_PROMPTпоэтому я могу найти несколько других вариантов:

1) Установите пакет от 12.04 - это не должно быть проблемой - в Python всего несколько скриптов, поэтому он должен работать (не проверено!).

2) Изменить stderrна stdout. Для того, чтобы сделать это отредактировать файл /usr/lib/python2.7/dist-packages/CommandNotFound/CommandNotFound.pyи изменения stderrв stdoutв строках 237 и 240.

После этого вы можете использовать его следующим образом:

pbm@ubuntu:~$ git
The program 'git' is currently not installed.  You can install it by typing:
sudo apt-get install git
pbm@ubuntu:~$ `git`
//Installation begins

Если вы добавите -yопцию к apt-getкоманде в строках 237 и 240, вы также можете использовать синтаксис !! | sh.

3) Вы также можете изменить этот скрипт из строки 242 следующим образом:

print >> sys.stderr, _("You can install it by typing:")
f = open("%s/.install-missing" % os.path.expanduser('~'),'w')
print >> sys.stderr, "sudo apt-get install %s" % packages[0][0]
print >> f, "sudo apt-get install %s" % packages[0][0]
f.close()

Таким образом, вы получите свою команду в файле ~/.install-missing, поэтому вы можете создать псевдоним:

alias im="chmod +x ~/.install-missing; ~/.install-missing"

Если вы позвоните imпакет будет установлен.

постоянный репер
источник
Хм, это выглядело действительно хорошо, но на самом деле, кажется, не работает на 11.10 oneiric, /usr/lib/command-not-foundно не имеет никакого отношения к COMMAND_NOT_FOUND_INSTALL_PROMPT- мысли?
cwd
Хорошо, похоже, что эта функция будет частью версии 12.04 ( package-import.ubuntu.com/diffs/command-not-found ). Я думаю, мне все еще нужно решение для более ранних версий.
cwd
@cwd: я обновил свой ответ ...
pbm
3

Вы были на правильном пути с:

!! 2>&1 | tail -n 1 | sh

... но вам не хватает опции ш . Рассматривать:

!! 2>&1 | tail -n 1 | sh -s

А так как вам, вероятно, нужен root-доступ для запуска apt-get, подумайте:

!! 2>&1 | tail -n 1 | sudo sh -s
СТТ
источник
Это не работает Sh и Sh-S делает то же самое, по крайней мере, в этом случае.
Дипак Миттал
1

Вы можете сделать что-то вроде этого:

!! 2>&1 | tail -n 1 > /tmp/cmd; bash /tmp/cmd; rm /tmp/cmd

Интерактивные программы, похоже, плохо работают с конвейером, потому что он ожидает ввода, в данном случае «Y», но дескриптор файла stdin закрывается, как только первая команда завершается.

Дипак Миттал
источник
0

evalЯ думаю, вы можете использовать переменную и подстановку команд (хотя я не уверен, насколько это безопасно):

TEST_VAR=$(!! 2>&1 | tail -n 1); eval $TEST_VAR

Я желаю быть доказанным неправильно с вышеупомянутым. Я тестирую это на машине Red Hat с echoкомандой, а не с автоматическим предложением завершения bash, но принцип должен быть таким же.

В конце концов, было бы быстрее набрать aptitude install git ...

webtoe
источник