Jak ponownie wykorzystać ostatnie wyjście z wiersza poleceń?


43

Chciałbym wiedzieć, jak ponownie wykorzystać ostatnie wyjście z konsoli, tj .:

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
Nie możesz; istnieje pewne tło wyjaśnienie tutaj . Najlepiej jest ponownie uruchomić polecenie, jak widać w dwóch dotychczasowych odpowiedziach.
— Gilles „SO- przestań być zły”

Nie można przechwytywać danych wyjściowych wysyłanych bezpośrednio do urządzenia, takiego jak /dev/tty, ale powinno być możliwe przechwytywanie wszystkiego wysyłanego do stdoutlub stderr, co może być odpowiednie.
— Mikel

@Gilles - oczywiście jeśli nie użyjesz odpowiedzi @ mattdm!
— simon

@Gilles: ale może istnieć powłoka utworzona przez kogoś, kto przechwyci (i przejdzie) dane wyjściowe poleceń i udostępni przechwycone dane wyjściowe, z których będzie mógł korzystać użytkownik. Być może istnieją nawet niektóre, nie tak popularne pociski, które pozwalają na mniej lub bardziej skomplikowane komplikacje ...
— imz - Ivan Zakharyaschev

Odpowiedzi:


39

Zakładając 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
Dzięki! Nie jest zbyt łatwe do pisania, ale bije mysz.
— methodofaction

2
Możesz także użyć backticków (których nie potrafię wymyślić, aby ten interfejs nie był wikikowany) zamiast $ (), ale stwierdziłem, że nie jest mi wygodnie naciskać backtick-shift-1-shift-1-backtick i staram się przyzwyczaić do używania $ (), gdy jest to możliwe ze względu na czytelność.
— jsbillings 11.03.11

@jsbillings patrz moja odpowiedź poniżej. W odpowiedzi wpisałem \, aby wyświetlić `. Aby wyświetlić „\”, jak zwykle wpisz „\\”.
— yasouser

3
+1 Zastanawiam się, jak zagnieżdżać `backtick-commands`! cd $(dirname $(which python))nadchodzę!
— Ed Brannin,

21
Tylko uwaga, pamiętaj, że jest to ponowne uruchamianie polecenia. Jeśli twoje polecenie ma skutki uboczne, może to nie działać dla ciebie.
— Rich Homolka

13

Nie wspomniano jeszcze, użyj zmiennej:

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

3
Dokładnie. Ponieważ jest to powłoka, ludzie często zapominają o funkcjach językowych udostępnianych przez Bash, takich jak pętle i zadania.
— Evan,

mogę po prostu powiedziećcd $dir
— tymczasowego

3
@Aerovistae, cytaty są wymagane, jeśli nie wiesz, skąd pochodzi wartość:
— glenn jackman

@glenn, (wiem, że to może być całe inne pytanie, ale jeśli odpowiedź jest krótka :) czy mógłbyś wyjaśnić więcej / podać przykład, w którym niestosowanie cudzysłowów mogłoby popsuć?
— Alexey,


8

Wszystkie pozostałe rozwiązania obejmują modyfikację przepływu pracy lub dwukrotne uruchomienie polecenia, co może nie być odpowiednie, jeśli uruchomienie zajmuje dużo czasu lub nie jest powtarzalne (np. Usuwa plik - ponowne uruchomienie spowodowałoby inny wynik).

Oto bardziej skomplikowany pomysł, jeśli go potrzebujesz:

.bashrc

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

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

trap 'rm ~/$$.out' EXIT

monit 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

Ma to pewne problemy, więc jest to po prostu punkt wyjścia. Na przykład plik wyjściowy ( ~/<pid>.out) może stać się bardzo duży i zapełnić dysk. Ponadto cała skorupa może przestać działać, jeśli teeumrze.

Można go zmodyfikować tak, aby przechwytywał dane wyjściowe z poprzedniego polecenia za pomocą preexeci precmdprzechwytuje w zsh lub emuluje je w bashu, ale bardziej skomplikowane jest to tutaj.


6
Podstawowy pomysł jest dobry, ale wdrożenie nie. Standardowym wyjściem w sesji powłoki nie jest terminal, lecz potok, który spowoduje, że niektóre programy będą zachowywać się inaczej. Nie będzie żadnej synchronizacji między zapisem na stdout a zapisem na stderr lub bezpośrednio do tty, więc na przykład możesz zobaczyć wynik polecenia wyświetlany po następnym znaku zachęty. Nie masz również ochrony teeprzed sygnałami (spróbuj nacisnąć Ctrl+Ci uruchomić więcej poleceń). Użyj scriptnarzędzia, które nie ma żadnego z tych problemów.
— Gilles 'SO - przestań być zły'

Dobrze wiedzieć! Nadal pracuję nad podstawami wiersza poleceń, więc jest to prawdopodobnie przesada dla mnie, a ponadto chcę móc używać go na dowolnym komputerze, ale zapamiętam to, jeśli kiedykolwiek osiągnę dobry poziom.
— methodofaction

8

Roboczy projekt tradycyjnej powłoki:

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

Teraz możemy przechwycić ekran do pliku. Potrzebuje sudo.

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

Apropos screendump: tak nazwany program już dla mnie nie działa. Może tylko dla starszych jąder. / dev / pts / N też dla mnie nie działał. Może masz jakieś opcjonalne MKDEV w / dev - o niektórych pamiętam ponuro /dev/cuaN, ale mogę się mylić.

Chcielibyśmy przesyłać dane wyjściowe zamiast używać screen.dump. Ale jakoś to nie działa - czasami czeka na ENTER.

Przechwytywanie nie jest zwykłym plikiem tekstowym z liniami, ale z - na przykład - znakami 80x50 w jednej sekwencji.

Aby wybrać ostatnie 2 wiersze, 1 dla wyniku polecenia i jeden dla wiersza polecenia, cofam go, wybieram 160 znaków, cofam ponownie i wybieram 80.

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

Na wszelki wypadek zastanawiałeś się, dlaczego istnieje revprogram.

Krytyka:

  • Wprowadzane są pierwsze polecenia, przesuwając linię. Cóż - po prostu ćwiczenie numeryczne, aby wybrać trzecią ostatnią linię lub coś takiego. Pracowałem głównie w innym oknie.
  • Nie każdy ma ekran 80x50. No tak, wiemy. Dla Twojej przyjemności są $ COLUMNS i $ ROWS.
  • Wynik nie zawsze jest na dole. Świeża i młoda skorupa może znajdować się w wyższych rzędach. Cóż - to proste: oceń, która powłoka działa. Który monit jest używany. Wykonaj szybkie wykrywanie i znajdź ostatni wiersz za pomocą polecenia powłoki. Linia przed (lub 2. przed) powinna zawierać katalog.

Pierwszy schemat jest wykonany za pomocą replace.py


+1, zmusił mnie do zrobieniaalias tee2tty='tee $(readlink /proc/$$/fd/1)'
— Tobias Kienzler

7

Spróbuj tego:

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

6

Oto odpowiedź:

Jeśli korzystasz z X, wybierz dane wyjściowe za pomocą myszy, aby je skopiować, a następnie kliknij środkowym przyciskiem myszy, aby je wkleić.

Jeśli korzystasz z konsoli tekstowej, możesz zrobić podobnie z gpm .


1
+1 - dobra odpowiedź! możesz osiągnąć to samo, nawet jeśli nie korzystasz z X, używając ekranu GNU ( gnu.org/software/screen ).
— Simon

1
Wydawało się to tak oczywiste, że wahałem się to powiedzieć. Ale wszyscy inni są tak zajęci byciem sprytnym. :)
— mattdm,

jest to jedyna odpowiedź, która pozwala OP ponownie wykorzystać ostatnią linię - wszystko inne wymaga ponownego uruchomienia polecenia, co może być gdzieś pomiędzy całkowicie nieistotnym i katastrofalnym :) Ale OP powiedział, że ponownie używa .
— simon

@simon: W rzeczywistości moja odpowiedź nie. Glenn też nie.
— Mikel

@Mikel: To prawda, ale wymagają one zrobienia czegoś wcześniej lub poprawnie za pierwszym razem.
— mattdm

1

(Niestety nie jest to robocza odpowiedź, ale wciąż coś ciekawego. Ktoś zainteresowany mógłby spróbować ukończyć implementację funkcji, o której ci powiem.)

W eshellśrodku Emacs, chcieli mieć taką funkcję, a jednak nie jest realizowane w sposób kompletny (co jest jednak odzwierciedlenie w dokumentacji ).

Na przykład:

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

~ $ 

Widzisz, tylko dane wyjściowe wbudowanych mogą być przechwytywane do $$zmiennej.

Ale cóż, niektóre programowanie elisp (por. eshell-mark-outputImplementacja w „esh-mode.el”) i można zaimplementować funkcję, która „zaznacza” ostatnie wyjście i zwraca je jako wynik funkcji; abyś mógł użyć tej funkcji w żądanym poleceniu eshell - funkcje elisp mogą być używane w poleceniach eshell ze zwykłą składnią elisp, tj. w nawiasach, takich jak:

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

0

Jeśli zdasz sobie sprawę, że będziesz chciał ponownie wykorzystać dane wyjściowe przed trafieniem Enter, możesz zapisać je w zmiennej: dodaj tmp=$(na początku wiersza i )na końcu. (Spowoduje to usunięcie pustej linii na końcu danych wyjściowych polecenia i w rzeczywistości usuwa końcową nową linię; to rzadko ma znaczenie).

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

Jeśli twoją powłoką jest ksh lub zsh, oto przydatna funkcja, której możesz użyć, aby uczynić ją bardziej automatyczną. (Bash nie pomaga, ponieważ wymaga wykonania ostatniego polecenia w potoku w powłoce nadrzędnej, co ma miejsce tylko w przypadku ksh (nie pdksh) i zsh.)

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

Użyj tego w ten sposób:

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

(w oparciu o odpowiedź 4485 )

To dużo pisania, więc zrób alias:

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

Następnie po prostu zadzwoń cd $(python -c ... | tee2tty)

To oczywiście wymaga, abyś już wiedział, co chcesz zrobić z wyjściem, ale ma tę zaletę, że wywołuje polecenie tylko raz.



0

Istnieje lepsze rozwiązanie:

Wystarczy wydrukować !!po wykonaniu polecenia, a otrzymasz powtarzalne wyjście.

Na przykład

wprowadź opis zdjęcia tutaj

Oryginał:

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


!!nie powtarza wyniku ostatniego polecenia, ponownie uruchamia ostatnie polecenie. Jeśli jot -r 1 0 1000zwróci pojedynczą liczbę losową z przedziału od 0 do 1000, po jednokrotnym uruchomieniu tej komendy i uzyskaniu jej 539uruchomienie !!najprawdopodobniej poda inną liczbę. !!może być również niepożądane, jeśli poprzednie polecenie zajmuje dużo czasu lub powtarza operację, której nie należy powtarzać (np. zmianę pliku).
— Caleb

1
dobry chwyt. Chociaż istnieje łatwiejszy sposób, aby udowodnić, że się mylę: echo $ RANDOM; !!
— Tebe

Słodko - nie wiedziałem o tym! Dzięki.
— Caleb
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.