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

43

Я хотел бы знать, как повторно использовать последний вывод из консоли, то есть:

pv-3:method Xavier$ python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()"
/Library/Python/2.6/site-packages
pv-3:method Xavier$ cd **LASTOUTPUT**
methodofaction
источник
7
Вы не можете; есть некоторое вводное объяснение здесь . Лучше всего снова запустить команду, как видно из двух ответов, опубликованных до сих пор.
Жиль "ТАК - перестань быть злым"
Вы не можете захватывать выходные данные, отправленные непосредственно на такое устройство, как /dev/tty, но должна быть возможность захватывать все, что отправлено stdoutили stderr, что может быть адекватным.
Микель
@ Жиль - если, конечно, ты не используешь ответ @ mattdm!
Симон
@Gilles: но кто-то может создать оболочку, которая будет захватывать (и проходить через) выходные данные команд и делать захваченные выходные данные доступными для пользователя, к которым можно обратиться из его дальнейших команд. Возможно, есть даже некоторые существующие, не очень популярные оболочки, которые позволяют это с более или менее сложными
последствиями
1
возможный дубликат использования текста из предыдущих команд 'output
Gilles' SO- перестань быть злым '21

Ответы:

39

Предполагая bash:

% python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()"
/usr/lib/python2.7/site-packages
% cd $(!!)
cd $(python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")
% pwd
/usr/lib/python2.7/site-packages
jsbillings
источник
1
Благодарность! Не слишком легко печатать, но это лучше, чем мышка.
methodofaction
2
Вы также можете использовать обратные пометки (которые я не могу понять, как сделать этот интерфейс не викифицированным) вместо $ (), но я обнаружил, что мне неудобно нажимать backtick-shift-1-shift-1-backtick и я пытаюсь привыкнуть использовать $ (), когда это возможно, для удобства чтения.
Jsbillings
@jsbillings смотрите мой ответ ниже. Я набрал \ `чтобы отобразить` в ответе. И для отображения '\', как обычно, введите '\\'.
yasouser
3
+1 Мне было интересно, как вложить `backtick-commands`! cd $(dirname $(which python))вот и я!
Эд Браннин,
21
Просто заметьте, помните, что это повторный запуск команды. Если у вашей команды есть побочные эффекты, это может не сработать для вас.
Богатая Гомолка
13

Пока не упоминается, используйте переменную:

dir=$( python -c ... )
cd "$dir"
Гленн Джекман
источник
3
В точку. Поскольку это оболочка, люди часто забывают о языковых возможностях, которые предоставляет Bash, таких как циклы и присваивание.
Эван
могу просто сказатьcd $dir
временное_имя_пользователя
3
@Aerovistae, кавычки необходимы, если вы не знаете, откуда
взято
@glenn, (я знаю, что это может быть совсем другой вопрос, но если ответ будет коротким :), не могли бы вы объяснить больше / привести пример, где не использование кавычек может сломать вещи?
Алексей
2
Каноническое объяснение: unix.stackexchange.com/questions/171346/…
Гленн Джекман
8

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

Итак, вот более сложная идея, если вам это нужно:

.bashrc

exec > >(tee -a ~/$$.out)

PROMPT_COMMAND='LASTLINE=$(tail -n 1 ~/$$.out)'

trap 'rm ~/$$.out' EXIT

приглашение bash

$ python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()"
/usr/lib/python2.6/dist-packages
$ cd $LASTLINE
$ pwd
/usr/lib/python2.6/dist-packages

У этого есть некоторые проблемы, так что это просто означает отправную точку. Например, выходной файл ( ~/<pid>.out) может стать очень большим и заполнить ваш диск. Кроме того, вся ваша оболочка может перестать работать, если teeумрет.

Его можно изменить так, чтобы он захватывал только выходные данные предыдущей команды, используя preexecи precmdловушки в zsh, или их эмуляцию в bash, но здесь это сложнее описать.

Mikel
источник
6
Основная идея хороша, но реализация - нет. Стандартный вывод в сеансе оболочки - это не терминал, а канал, что приводит к тому, что некоторые программы ведут себя по-разному. Не будет никакой синхронизации между записью в stdout и записью в stderr или напрямую в tty, поэтому, например, вы можете увидеть вывод команды после следующего запроса. Вы также не защищены teeот сигналов (попробуйте нажать Ctrl+Cи запустить несколько команд). Используйте scriptутилиту, у которой нет ни одной из этих проблем.
Жиль "ТАК - перестань быть злым"
Хорошо знать! Я все еще работаю над основами командной строки, так что, возможно, это излишнее для меня, плюс я хочу иметь возможность использовать его на любом компьютере, но я запомню это, если когда-нибудь достигну хорошего уровня.
methodofaction
8

Рабочий проект для традиционной оболочки:

ttyid=$(readlink /proc/$$/fd/1)
\___/   \______/ \___/ |  |  |
  |         |      |   |  |  \- 0: stdin 
  |         |      |   |  |     1: stdout <- our interest
  |         |      |   |  |     2: stderr
  |         |      |   |  \- fd is, maybe, filedescriptor
  |         |      |   |
  |         |      |   \- $$ is the PID of the current process (shell,
  |         |      |      in our case)
  |         |      |
  |         |      \- you know, much runtime stuff is here
  |         |
  |         \- readlink extracts the symbolic link of /proc/$$/fd/1
  |            lrwx------ 1 stefan stefan 64 2011-03-18 09:11
  |            /proc/22159/fd/1 -> /dev/pts/4
  |
  \- /dev/tty3 for real shell, /dev/pts/3 for xterm

Теперь мы можем поместить экран в файл. Необходимо sudo.

id=${ttyid//\/dev\/tty}
sudo cat /dev/vcs$id > screen.dump

Кстати screendump: так называемая программа больше не работает для меня. Может быть, только для старых ядер. / dev / pts / N тоже не работает для меня. Может быть, вам нужен какой-нибудь дополнительный MKDEV в / dev - я немного помню о некоторых /dev/cuaN, но могу ошибаться.

Мы хотели бы передать вывод вместо использования screen.dump. Но так или иначе это не работает - иногда это ждет ENTER.

Захват не обычный текстовый файл с переводами строки, но с - например - 80x50 символов в одной последовательности.

Чтобы выбрать последние 2 строки, 1 для вывода команды и одну для строки подсказки, я возвращаю ее, выбираю 160 символов, снова возвращаюсь и 80.

rev vcs4.dat | sed 's/\(.\{160\}\).*/\1/g' | rev | sed 's/\(.\{80\}\).*/\1/g'

На тот случай, если вы когда-нибудь задумывались, почему существует revпрограмма.

Критика:

  • Первые команды вводятся, тем самым сдвигая строку вперед. Хорошо - просто числовое упражнение, чтобы выбрать 3-ю последнюю строчку или что-то в этом роде. Я работал в основном в другом окне.
  • Не у всех есть экран 80х50. Ну да, мы знаем. Для вашего удовольствия есть $ COLUMNS и $ ROWS.
  • Выход не всегда внизу. Свежая и молодая раковина может быть в верхних рядах. Что ж, все просто: оцените, какая оболочка работает. Какая подсказка используется. Сделайте некоторое быстрое обнаружение и найдите последнюю строку с приглашением оболочки. Строка перед (или 2. перед) должна содержать каталог.

Первая диаграмма сделана с объяснением

неизвестный пользователь
источник
+1, заставил меня сделатьalias tee2tty='tee $(readlink /proc/$$/fd/1)'
Тобиас Кинцлер
7

Попробуй это:

$ cd $(python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")
$ pwd
/Library/Python/2.6/site-packages
bahamat
источник
6

Итак, вот ответ:

Если вы работаете под X, выберите нужный вывод мышью, чтобы скопировать его, а затем нажмите среднюю кнопку мыши, чтобы вставить его.

Если вы работаете в текстовой консоли, вы можете сделать то же самое с gpm .

mattdm
источник
1
+1 - хороший ответ! вы можете добиться того же, даже если вы не используете X, используя экран GNU ( gnu.org/software/screen ).
Симон
1
Это казалось настолько очевидным, что я не решался сказать это. Но все остальные так заняты умом. :)
mattdm
это единственный ответ, который позволяет OP повторно использовать последнюю строку - все остальное влечет за собой повторное выполнение команды, что может быть где-то между совершенно неуместным и катастрофическим :) Но OP сказал повторное использование .
Симон
@ Симон: На ​​самом деле мой ответ не так. Ни один не делает Гленна.
Микель
@Mikel: Да, но они требуют, чтобы вы что-то делали заранее или правильно в первый раз.
Mattdm
1

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

В eshellвнутри Emacs, они хотели бы иметь такую возможность , но это не реализовано в полном виде (который, однако , отраженный в документации ).

Например:

~ $ pwd
~
~ $ /bin/echo $$
~
~ $ /bin/pwd
/home/imz
~ $ /bin/echo $$

~ $ 

Видите ли, только выходные данные встроенных могут быть записаны в $$переменную.

Но хорошо, немного elisp-программирования (см. eshell-mark-outputРеализацию в «esh-mode.el»), и вы могли бы реализовать функцию, которая «помечает» последний вывод и возвращает его как результат функции; чтобы вы могли использовать эту функцию в запрашиваемой команде eshell - функции elisp можно использовать в командах eshell с обычным синтаксисом elisp, то есть в скобках, например так:

~ $ /bin/echo (buffer-name)
*eshell*
~ $ /bin/echo (car '(a b c))
a
~ $ 
imz - Иван Захарящев
источник
0

Если вы понимаете, что захотите повторно использовать вывод до того, как нажмете Enter, вы можете сохранить его в переменной: добавить tmp=$(в начале строки и )в конце. (Это удаляет любую пустую строку в конце вывода команды и фактически удаляет любой заключительный символ новой строки; это редко имеет значение.)

tmp=$(python -c )
echo "$tmp"
cd "$tmp"

Если ваша оболочка ksh или zsh, вот полезная функция, которую вы можете использовать, чтобы сделать ее более автоматической. (Это не помогает в bash, поскольку требует, чтобы последняя команда конвейера выполнялась в родительской оболочке, что имеет место только в ksh (не pdksh) и zsh.)

keep () {
  local line IFS=$'\n'
  kept=
  while read -r line; do
    printf '%s\n' "$line"
    kept=$kept$line$IFS
  done
}
alias keep=k

Используйте это так:

python -c  |k
cd $kept
Жиль "ТАК - перестань быть злым"
источник
0
cd $(python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()" | tee $(readlink /proc/$$/fd/1))

(основываясь на ответе 4485 )

Это много печатать, поэтому сделайте псевдоним:

alias tee2tty='tee $(readlink /proc/$$/fd/1)'

Тогда просто позвони cd $(python -c ... | tee2tty)

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

Тобиас Кинцлер
источник
0
$ cd \`python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()"\`

сделает свое дело.

Подробнее читайте здесь: Подстановка команд .

yasouser
источник
1
arumug: Багамат уже опубликовал почти тот же ответ . Ваша версия с обратными галочками не всегда будет работать, если в команде уже есть обратные галочки.
Жиль "ТАК - перестань быть злым"
0

Есть лучшее решение:

Просто напечатайте !!после выполненной команды, и вы получите повторный вывод.

Например

введите описание изображения здесь

Оригинал:

https://askubuntu.com/questions/324423/how-to-access-the-last-return-value-in-bash

Теб
источник
!!не повторяет результат последней команды, он повторно запускает последнюю команду. Если jot -r 1 0 1000возвращает одно случайное число в диапазоне от 0 до 1000, то после однократного запуска этой команды и ее 539запуска !!, скорее всего , будет выдано другое число. !!также может быть нежелательным, если выполнение предыдущей команды занимает много времени или повторяет операцию, которая не должна повторяться (например, изменение файла).
Калеб
1
Хорошо поймал. Хотя есть более простой способ доказать, что я не прав: echo $ RANDOM; !!
Тебе
Сладкий - не знал об этом! Спасибо.
Калеб