Come riutilizzare l'ultimo output dalla riga di comando?


43

Vorrei sapere come riutilizzare l'ultimo output dalla console, ovvero:

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**

7
Non puoi; c'è qualche spiegazione di base qui . La soluzione migliore è eseguire nuovamente il comando, come si vede nelle due risposte pubblicate finora.
Gilles 'SO- smetti di essere malvagio' il

Non è possibile acquisire l'output inviato direttamente a un dispositivo come /dev/tty, ma dovrebbe essere possibile acquisire qualsiasi elemento inviato a stdouto stderr, che potrebbe essere adeguato.
Mikel

@Gilles - a meno che tu non usi la risposta di @ mattdm, ovviamente!
simon

@Gilles: ma potrebbe esserci una shell creata da qualcuno che catturerà (e passerà attraverso) gli output dei comandi e renderà disponibili gli output acquisiti a cui l'utente può fare riferimento dai suoi ulteriori comandi. Forse, ci sono anche alcune conchiglie esistenti, non così popolari che lo consentono con più o meno complicazioni ...
imz - Ivan Zakharyaschev

Risposte:


39

Supponendo 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

1
Grazie! Non troppo facile da scrivere ma batte per il mouse.
methodofaction

2
Potresti anche usare i backtick (che non riesco a capire come rendere questa interfaccia non wikify) invece di $ (), ma ho scoperto che è scomodo per me colpire backtick-shift-1-shift-1-backtick e sto cercando di prendere l'abitudine di usare $ () quando possibile per motivi di leggibilità.
jsbillings,

@jsbillings vedi la mia risposta qui sotto. Ho digitato \ `per visualizzare` nella risposta. E per visualizzare '\', come al solito digita '\\'.
Yasouser,

3
+1 Mi chiedevo come nidificare `backtick-commands`! cd $(dirname $(which python))eccomi!
Ed Brannin,

21
Solo una nota, ricorda che questo è ripetere il comando. Se il tuo comando ha effetti collaterali, questo potrebbe non funzionare per te.
Rich Homolka,

13

Non ancora menzionato, usa una variabile:

dir=$( python -c ... )
cd "$dir"

3
Esattamente. Poiché si tratta di una shell, le persone spesso dimenticano le funzionalità linguistiche fornite da Bash, come loop e assegnazioni.
Evan,

posso solo direcd $dir
temporaneo

3
@Aerovistae, le virgolette sono obbligatorie se non sai da dove proviene il valore:
glenn jackman,

@glenn, (So che questa potrebbe essere tutta un'altra domanda, ma se la risposta è breve :) potresti spiegare di più / fornire un esempio in cui non usare le virgolette romperebbe le cose?
alexey,


8

Tutte le altre soluzioni comportano la modifica del flusso di lavoro o l'esecuzione del comando due volte, il che potrebbe non essere adatto se richiede molto tempo per l'esecuzione o non è ripetibile (ad esempio, elimina un file - rieseguendo produrrebbe un risultato diverso).

Quindi, ecco un'idea più complicata se ne hai bisogno:

.bashrc

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

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

trap 'rm ~/$$.out' EXIT

prompt di 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

Questo ha alcuni problemi, quindi è solo inteso come punto di partenza. Ad esempio, il file di output ( ~/<pid>.out) potrebbe diventare molto grande e riempire il disco. Inoltre, l'intera shell potrebbe smettere di funzionare se teemuore.

Potrebbe essere modificato per catturare solo l'output del comando precedente usando preexece precmdhook in zsh, o una loro emulazione in bash, ma è più complicato descriverlo qui.


6
L'idea di base è buona, ma l'implementazione no. L'output standard nella sessione della shell non è un terminale ma una pipe, che farà sì che alcuni programmi si comportino in modo diverso. Non ci sarà alcuna sincronizzazione tra le scritture su stdout e le scritture su stderr o dirette su tty, quindi ad esempio potresti vedere l'output del comando visualizzato dopo il prompt successivo. Inoltre non hai protetto teedai segnali (prova a premere Ctrl+Ced eseguire altri comandi). Utilizzare l' scriptutilità che non presenta nessuno di questi problemi.
Gilles 'SO- smetti di essere malvagio' il

Buono a sapersi! Sto ancora lavorando sulle basi della mia riga di comando, quindi questo è forse un problema per me, inoltre voglio poterlo usare su qualsiasi computer, ma lo ricorderò se raggiungerò mai un buon livello.
methodofaction

8

Una bozza di lavoro per un guscio tradizionale:

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

Ora possiamo collegare lo schermo a un file. Ha bisogno di sudo.

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

A proposito screendump: il cosiddetto programma non funziona più per me. Forse solo per i kernel più vecchi. / dev / pts / N non ha funzionato anche per me. Forse devi avere qualche MKDEV opzionale in / dev - mi ricordo cupamente di alcuni /dev/cuaN, ma potrei sbagliarmi.

Vorremmo reindirizzare l'output invece di utilizzare screen.dump. Ma in qualche modo non funziona - a volte aspetta INVIO.

L'acquisizione non è un normale file di testo con avanzamenti di riga, ma con - ad esempio - caratteri 80x50 in una sequenza.

Per selezionare le ultime 2 righe, 1 per l'output del comando e una per la riga di prompt, la ripristino, seleziono 160 caratteri, ripristiniamo di nuovo e seleziono 80.

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

Nel caso in cui ti sia mai chiesto, perché esiste un revprogramma.

Critica:

  • Vengono immessi i primi comandi, spostando così la linea. Bene - solo un esercizio numerico per scegliere la terza riga o qualcosa del genere. Ho lavorato principalmente in un'altra finestra.
  • Non tutti hanno uno schermo 80x50. Beh, sì, lo sappiamo. Ci sono $ COLONNE e $ FILI per il tuo piacere.
  • L'output non è sempre in fondo. Un guscio fresco e giovane potrebbe essere nelle file superiori. Bene - semplice: valuta quale shell è in esecuzione. Quale prompt viene utilizzato. Esegui un rapido rilevamento e trova l'ultima riga con un prompt della shell. La riga prima (o 2. prima) dovrebbe contenere la directory.

Il primo diagramma è realizzato con spiegato.py


+1, mi ha fatto farealias tee2tty='tee $(readlink /proc/$$/fd/1)'
Tobias Kienzler il

7

Prova questo:

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

6

Quindi, ecco una risposta:

Se stai utilizzando X, seleziona l'output desiderato con il mouse per copiarlo, quindi fai clic con il pulsante centrale per incollarlo.

Se stai utilizzando una console di testo, puoi fare una cosa simile con gpm .


1
+1 - buona risposta! potresti ottenere la stessa cosa, anche se non usi X, usando lo schermo GNU ( gnu.org/software/screen ).
Simon

1
Sembrava così ovvio che ero titubante nel dirlo. Ma tutti gli altri sono così impegnati a essere intelligenti. :)
mattdm,

è l'unica risposta qui che consente all'OP di riutilizzare l'ultima riga - tutto il resto comporta l'esecuzione del comando di nuovo, che potrebbe essere ovunque tra assolutamente irrilevante e catastrofico :) Ma l'OP ha detto di riutilizzare .
simon

@simon: In realtà, la mia risposta no. Nemmeno Glenn's.
Mikel,

@Mikel: Vero, ma richiedono che tu faccia qualcosa in anticipo o correttamente la prima volta.
Mattdm,

1

(Purtroppo non è una risposta funzionante, ma comunque qualcosa di curioso. Qualcuno interessato potrebbe provare a completare l'implementazione della funzione di cui ti parlerò.)

In eshelldentro Emacs, volevano avere come caratteristica un ma non è implementata in modo completo (che però viene riflessa nella documentazione ).

Per esempio:

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

~ $ 

Vedete, solo l'output dei builtin può essere catturato nella $$variabile.

Ma bene, qualche programmazione elisp (vedi eshell-mark-outputimplementazione in "esh-mode.el"), e potresti implementare una funzione che "segna" l'ultimo output e lo restituisce come risultato della funzione; in modo che tu possa usare quella funzione in un comando eshell che stai chiedendo - le funzioni elisp possono essere usate nei comandi eshell con la solita sintassi elisp, cioè tra parentesi, come questa:

~ $ /bin/echo (buffer-name)
*eshell*
~ $ /bin/echo (car '(a b c))
a
~ $ 

0

Se ti rendi conto che vorrai riutilizzare l'output prima di colpire Enter, puoi salvarlo in una variabile: aggiungi tmp=$(all'inizio della riga e )alla fine. (Ciò rimuove qualsiasi riga vuota alla fine dell'output del comando, e di fatto rimuove qualsiasi nuova riga finale; questo raramente conta.)

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

Se la tua shell è ksh o zsh, ecco una funzione utile che puoi usare per renderla più automatica. (Non è d'aiuto in bash perché richiede che l'ultimo comando in una pipeline sia eseguito nella shell genitore, che è solo il caso in ksh (non in pdksh) e zsh.)

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

Usalo in questo modo:

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))

(basandosi sulla risposta del 4485 )

È un sacco di digitazione, quindi crea un alias:

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

Quindi chiama semplicemente cd $(python -c ... | tee2tty)

Questo ovviamente richiede che tu sappia già cosa vuoi fare con l'output ma ha il vantaggio di chiamare il comando solo una volta.



0

C'è una soluzione migliore:

Basta stampare !!dopo aver eseguito il comando e otterrai risultati ripetuti.

Per esempio

inserisci qui la descrizione dell'immagine

Originale:

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


!!non ripete il risultato dall'ultimo comando, esegue nuovamente l'ultimo comando. Se jot -r 1 0 1000restituisce un singolo numero casuale compreso tra 0 e 1000, quindi dopo aver eseguito quel comando una volta e averlo ricevuto 539, l'esecuzione !!fornirà molto probabilmente un altro numero. !!può anche essere indesiderabile se l'esecuzione del comando precedente richiede molto tempo o se ripete un'operazione che non deve essere ripetuta (come la modifica di un file).
Caleb,

1
bella presa. Sebbene ci sia un modo più semplice per dimostrarmi che mi sbaglio: echo $ RANDOM; !!
Tebe,

Dolce - non lo sapevo! Grazie.
Caleb,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.