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**
methodofaction
źródło
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
1
możliwy duplikat użycia tekstu z wyników poprzednich poleceń
Gilles 'SO - przestań być zły'

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
jsbillings
źródło
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"
Glenn Jackman
źródło
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,
2
Wyjaśnienie kanoniczne to unix.stackexchange.com/questions/171346/…
glenn jackman
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.

Mikel
źródło
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

nieznany użytkownik
źródło
+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
bahamat
źródło
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 .

mattdm
źródło
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
~ $ 
imz - Ivan Zakharyaschev
źródło
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
Gilles „SO- przestań być zły”
źródło
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.

Tobias Kienzler
źródło
0
$ cd \`python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()"\`

da rade.

Przeczytaj tutaj, aby uzyskać więcej informacji: Zastępowanie poleceń .

yasouser
źródło
1
arumug: bahamat opublikował już prawie taką samą odpowiedź . Twoja wersja z backtickami nie zawsze będzie działać, jeśli w poleceniu są już backticksy.
Gilles „SO- przestań być zły”
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

Tebe
źródło
!!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