¿Cómo reutilizo la última salida de la línea de comando?

43

Me gustaría saber cómo reutilizar la última salida de la consola, es decir:

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**
método de acción
fuente
77
No puedes; Hay alguna explicación de fondo aquí . Su mejor opción es ejecutar el comando nuevamente, como se ve en las dos respuestas publicadas hasta ahora.
Gilles 'SO- deja de ser malvado'
No puede capturar la salida enviada directamente a un dispositivo como /dev/tty, pero debería ser posible capturar cualquier cosa enviada stdoutao stderr, lo que podría ser adecuado.
Mikel
@Gilles - ¡a menos que use la respuesta de @ mattdm, por supuesto!
Simon
@Gilles: pero podría haber un shell creado por alguien que capturará (y pasará) las salidas de los comandos y hará que las salidas capturadas estén disponibles para que el usuario las consulte desde sus comandos adicionales. Quizás, incluso hay algunos proyectiles existentes, no tan populares, que permiten esto con más o menos complicaciones ...
imz - Ivan Zakharyaschev
1
posible duplicado de Usar texto de la salida de comandos anteriores
Gilles 'SO- deja de ser malvado'

Respuestas:

39

Asumiendo 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
fuente
1
¡Gracias! No es demasiado fácil de escribir, pero es mejor que ir por el mouse.
methodofaction
2
También podría usar backticks (que no puedo entender cómo hacer que esta interfaz no sea wikify) en lugar de $ (), pero he encontrado que es incómodo para mí presionar backtick-shift-1-shift-1-backtick , y estoy tratando de acostumbrarme a usar $ () cuando sea posible por razones de legibilidad.
jsbillings
@jsbillings mira mi respuesta a continuación. Escribí \ `para mostrar` en la respuesta. Y para mostrar '\', como siempre, escriba '\\'.
yasouser
3
+1 ¡Me he estado preguntando cómo anidar `backtick-commands`! cd $(dirname $(which python))¡aquí vengo!
Ed Brannin
21
Solo una nota, recuerde que esto es volver a ejecutar el comando. Si su comando tiene efectos secundarios, esto puede no funcionar para usted.
Rich Homolka
13

Aún no mencionado, use una variable:

dir=$( python -c ... )
cd "$dir"
Glenn Jackman
fuente
3
Exactamente. Debido a que es un shell, las personas a menudo se olvidan de las características del lenguaje que proporciona Bash, como los bucles y la asignación.
Evan
puede simplemente decircd $dir
temporary_user_name
3
@Aerovistae, las cotizaciones son obligatorias si no sabe de dónde proviene el valor:
glenn jackman
@glenn, (sé que esta podría ser otra pregunta, pero si la respuesta es corta :) ¿podría explicar más / dar un ejemplo en el que no usar comillas rompería las cosas?
alexey
2
La explicación canónica es unix.stackexchange.com/questions/171346/…
glenn jackman el
8

Todas las demás soluciones implican modificar su flujo de trabajo o ejecutar el comando dos veces, lo que podría no ser adecuado si tarda mucho tiempo en ejecutarse o no es repetible (por ejemplo, elimina un archivo; volver a ejecutarlo produciría un resultado diferente).

Así que aquí hay una idea más complicada si la necesita:

.bashrc

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

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

trap 'rm ~/$$.out' EXIT

bash prompt

$ 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

Esto tiene algunos problemas, por lo que solo se entiende como un punto de partida. Por ejemplo, el archivo de salida ( ~/<pid>.out) puede crecer mucho y llenar su disco. Además, todo su caparazón podría dejar de funcionar si teemuere.

Podría modificarse para capturar solo la salida del comando anterior usando preexecy precmdganchos en zsh, o una emulación de ellos en bash, pero eso es más complicado de describir aquí.

Mikel
fuente
66
La idea básica es buena, pero la implementación no lo es. La salida estándar en la sesión de shell no es una terminal sino una tubería, lo que hará que algunos programas se comporten de manera diferente. No habrá sincronización entre las escrituras en stdout y las escrituras en stderr o directamente en el tty, por lo que, por ejemplo, es posible que se muestre la salida del comando después de la próxima solicitud. Tampoco se ha protegido teede las señales (intente presionar Ctrl+Cy ejecutar algunos comandos más). Use la scriptutilidad que no tiene ninguno de estos problemas.
Gilles 'SO- deja de ser malvado'
¡Bueno saber! Todavía estoy trabajando en los conceptos básicos de mi línea de comando, por lo que posiblemente sea una exageración para mí, además, quiero poder usarlo en cualquier computadora, pero lo recordaré si alguna vez alcanzo un buen nivel.
methodofaction
8

Un borrador de trabajo para una concha tradicional:

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

Ahora podemos pasar la pantalla a un archivo. Necesita sudo.

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

A propósito screendump: el llamado programa ya no funciona para mí. Tal vez solo para núcleos más antiguos. / dev / pts / N tampoco funcionó para mí. Tal vez tenga que usar algún MKDEV opcional en / dev. Recuerdo oscuramente algunos /dev/cuaN, pero puedo estar equivocado.

Nos gustaría canalizar la salida en lugar de usar screen.dump. Pero de alguna manera no funciona, a veces espera ENTER.

La captura no es un archivo de texto normal con saltos de línea, sino con, por ejemplo, 80x50 caracteres en una secuencia.

Para elegir las últimas 2 líneas, 1 para la salida del comando y una para la línea de aviso, la revierto, escojo 160 caracteres, revierto nuevamente y escojo 80.

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

Por si alguna vez te has preguntado, ¿por qué hay un revprograma?

Crítica:

  • Se ingresan los primeros comandos, moviendo así la línea ahed. Bueno, solo un ejercicio numérico para elegir la 3ra última línea o algo así. Trabajé principalmente en una ventana diferente.
  • No todos tienen una pantalla de 80x50. Pues sí, lo sabemos. Hay $ COLUMNS y $ ROWS para su placer.
  • La salida no está siempre en la parte inferior. Una concha fresca y joven podría estar en las filas superiores. Bueno, así de simple: evalúa qué shell se está ejecutando. Qué aviso se utiliza. Realice una detección rápida y encuentre la última línea con un indicador de comandos de shell. La línea anterior (o 2. anterior) debe contener el directorio.

El primer diagrama está hecho con explicar.py

usuario desconocido
fuente
+1, me obligó a hacerloalias tee2tty='tee $(readlink /proc/$$/fd/1)'
Tobias Kienzler
7

Prueba esto:

$ cd $(python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")
$ pwd
/Library/Python/2.6/site-packages
bahamat
fuente
6

Entonces, aquí hay una respuesta:

Si está ejecutando bajo X, seleccione el resultado que desea con el mouse para copiarlo y luego haga clic con el botón central para pegarlo.

Si está ejecutando en una consola de texto, puede hacer algo similar con gpm .

mattdm
fuente
1
+1 - ¡buena respuesta! podría lograr lo mismo, incluso si no está ejecutando X, utilizando la pantalla GNU ( gnu.org/software/screen ).
Simon
1
Parecía tan obvio que dudaba en decirlo. Pero todos los demás están tan ocupados siendo inteligentes. :)
mattdm
es la única respuesta aquí que permite que el OP reutilice la última línea; todo lo demás implica ejecutar el comando nuevamente, lo que podría ser entre absolutamente irrelevante y catastrófico :) Pero el OP sí dijo reutilizar .
Simon
@simon: En realidad, mi respuesta no. Tampoco Glenn's.
Mikel
@Mikel: Cierto, pero requieren que hagas algo de antemano o correctamente la primera vez.
mattdm
1

(Desafortunadamente, no es una respuesta que funcione, pero sigue siendo algo curioso. Alguien interesado podría intentar completar la implementación de la función que le voy a contar).

En el eshellinterior de Emacs, querían tener esa característica, pero no está implementada de manera completa (lo que, sin embargo, se refleja en la documentación ).

Por ejemplo:

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

~ $ 

Verá, solo la salida de los builtins se puede capturar en la $$variable.

Pero bueno, algo de programación elisp (cf. eshell-mark-outputimplementación en "esh-mode.el"), y podría implementar una función que "marca" la última salida y la devuelve como el resultado de la función; para que pueda usar esa función en un comando eshell que está solicitando: las funciones elisp se pueden usar en comandos eshell con la sintaxis elisp habitual, es decir, entre paréntesis, como este:

~ $ /bin/echo (buffer-name)
*eshell*
~ $ /bin/echo (car '(a b c))
a
~ $ 
imz - Ivan Zakharyaschev
fuente
0

Si se da cuenta de que va a querer reutilizar la salida antes de presionar Enter, puede guardarla en una variable: agregue tmp=$(al principio de la línea y )al final. (Esto elimina cualquier línea en blanco al final de la salida del comando, y de hecho elimina cualquier nueva línea final; esto rara vez importa).

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

Si su shell es ksh o zsh, aquí hay una función útil que puede usar para hacer esto más automático. (No es de ayuda en bash porque requiere que el último comando en una tubería se ejecute en el shell principal, que es solo el caso en ksh (no pdksh) y zsh).

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

Úselo de esta manera:

python -c  |k
cd $kept
Gilles 'SO- deja de ser malvado'
fuente
0
cd $(python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()" | tee $(readlink /proc/$$/fd/1))

(sobre la base de la respuesta de 4485 )

Eso es mucho escribir, así que crea un alias:

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

Entonces simplemente llame cd $(python -c ... | tee2tty)

Por supuesto, esto requiere que ya sepa lo que quiere hacer con la salida, pero tiene la ventaja de llamar al comando solo una vez.

Tobias Kienzler
fuente
0

Hay una mejor solución:

Simplemente imprima !!después del comando ejecutado y obtendrá resultados repetidos.

P.ej

ingrese la descripción de la imagen aquí

Original:

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

Tebe
fuente
!!no repite el resultado del último comando, vuelve a ejecutar el último comando. Si jot -r 1 0 1000devuelve un solo número aleatorio entre 0 y 1000, entonces, después de ejecutar ese comando una vez y obtener 539, la ejecución !!probablemente dará algún otro número. !!También puede ser indeseable si el comando anterior tarda mucho tiempo en ejecutarse o repite una operación que no debe repetirse (como cambiar un archivo).
Caleb
1
buena atrapada. Aunque hay una manera más fácil de demostrar que estoy equivocado: echo $ RANDOM; !!
Tebe
Dulce, ¡no sabía eso! Gracias.
Caleb