Bagaimana saya menggunakan kembali output terakhir dari baris perintah?

43

Saya ingin tahu cara menggunakan kembali output terakhir dari konsol, yaitu:

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**
metode tindakan
sumber
7
Kamu tidak bisa; ada beberapa penjelasan latar belakang di sini . Taruhan terbaik Anda adalah menjalankan perintah lagi, seperti yang terlihat dalam dua jawaban yang diposting sejauh ini.
Gilles 'SO- stop being evil'
Anda tidak dapat menangkap output yang dikirim langsung ke perangkat seperti itu /dev/tty, tetapi harus dimungkinkan untuk menangkap apa pun yang dikirim ke stdoutatau stderr, yang mungkin memadai.
Mikel
@Gilles - kecuali Anda menggunakan jawaban @ mattdm, tentu saja!
simon
@Gilles: tetapi mungkin ada shell yang dibuat oleh seseorang yang akan menangkap (dan melewati) output dari perintah dan membuat output yang ditangkap tersedia bagi pengguna untuk merujuk dari perintah selanjutnya. Mungkin, bahkan ada beberapa kerang yang ada dan tidak begitu populer yang memungkinkan ini dengan lebih atau kurang komplikasi ...
imz - Ivan Zakharyaschev
1
kemungkinan duplikat Menggunakan teks dari perintah 'keluaran' sebelumnya
Gilles 'SO-stop evil'

Jawaban:

39

Dengan asumsi 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
sumber
1
Terima kasih! Tidak terlalu mudah untuk mengetik tetapi itu mengalahkan untuk mouse.
methodofaction
2
Anda juga dapat menggunakan backticks (yang saya tidak tahu cara membuat antarmuka ini tidak menggerakkan) daripada $ (), tetapi saya merasa tidak nyaman bagi saya untuk menekan backtick-shift-1-shift-1-backtick , dan saya mencoba membiasakan diri menggunakan $ () jika memungkinkan demi keterbacaan.
jsbillings
@ jsbillings lihat jawaban saya di bawah ini. Saya mengetik \ `untuk menampilkan` dalam jawabannya. Dan untuk menampilkan '\', seperti biasa ketik '\\'.
yasouser
3
+1 Saya sudah bertanya-tanya bagaimana cara bersarang `backtick-commands`! cd $(dirname $(which python))aku datang!
Ed Brannin
21
Hanya sebuah catatan, ingat bahwa ini menjalankan kembali perintah. Jika perintah Anda memiliki efek samping, ini mungkin tidak cocok untuk Anda.
Rich Homolka
13

Belum disebutkan, gunakan variabel:

dir=$( python -c ... )
cd "$dir"
glenn jackman
sumber
3
Persis. Karena ini adalah shell, orang sering lupa tentang fitur bahasa yang disediakan Bash, seperti loop dan tugas.
Evan
bisa saja mengatakancd $dir
temporary_user_name
3
@Aerovistae, tanda kutip diperlukan jika Anda tidak tahu dari mana nilai itu berasal:
glenn jackman
@glenn, (saya tahu ini bisa menjadi pertanyaan lain, tetapi jika jawabannya singkat :) bisakah Anda menjelaskan lebih lanjut / memberikan contoh di mana tidak menggunakan tanda kutip akan merusak banyak hal?
alexey
2
Penjelasan kanonik adalah unix.stackexchange.com/questions/171346/…
glenn jackman
8

Semua solusi lain melibatkan memodifikasi alur kerja Anda atau menjalankan perintah dua kali, yang mungkin tidak cocok jika perlu waktu lama untuk dijalankan, atau tidak dapat diulang (misalnya menghapus file - menjalankan kembali akan menghasilkan hasil yang berbeda).

Jadi, inilah ide yang lebih rumit jika Anda membutuhkannya:

.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

Ini memiliki beberapa masalah, jadi itu hanya dimaksudkan sebagai titik awal. Misalnya, file output ( ~/<pid>.out) mungkin tumbuh sangat besar dan mengisi disk Anda. Selain itu, seluruh kulit Anda bisa berhenti bekerja jika teemati.

Itu bisa dimodifikasi untuk hanya menangkap output dari perintah sebelumnya menggunakan preexecdan precmdkait di zsh, atau emulasi dari mereka di bash, tapi itu lebih rumit untuk dijelaskan di sini.

Mikel
sumber
6
Ide dasarnya bagus, tetapi implementasinya tidak. Output standar dalam sesi shell bukan terminal tetapi pipa, yang akan menyebabkan beberapa program berperilaku berbeda. Tidak akan ada sinkronisasi antara menulis ke stdout dan menulis ke stderr atau mengarahkan ke tty, jadi misalnya Anda mungkin melihat output perintah ditampilkan setelah prompt berikutnya. Anda juga belum terlindungi teedari sinyal (coba tekan Ctrl+Cdan jalankan beberapa perintah lagi). Gunakan scriptutilitas yang tidak memiliki masalah ini.
Gilles 'SANGAT berhenti menjadi jahat'
Senang mendengarnya! Saya masih bekerja pada dasar-dasar baris perintah saya jadi ini mungkin merupakan kerja keras bagi saya, ditambah saya ingin dapat menggunakannya di komputer mana pun, tetapi saya akan mengingatnya jika saya pernah mencapai level yang baik.
methodofaction
8

Draf kerja untuk shell tradisional:

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

Sekarang kita bisa menampilkan layar ke file. Membutuhkan sudo.

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

Apropos screendump: program yang dinamai itu tidak bekerja lagi untuk saya. Mungkin hanya untuk kernel yang lebih tua. / dev / pts / N tidak bekerja untuk saya juga. Mungkin Anda harus ke beberapa opsional MKDEV di / dev - Saya ingat dengan keliru tentang beberapa /dev/cuaN, tapi saya mungkin salah.

Kami ingin menyalurkan output daripada menggunakan screen.dump. Tapi entah bagaimana itu tidak berhasil - kadang-kadang menunggu ENTER.

Pengambilan bukan file teks normal dengan umpan baris, tetapi dengan - misalnya - karakter 80x50 dalam satu urutan.

Untuk memilih 2 baris terakhir, 1 untuk output dari perintah, dan satu untuk baris yang meminta, saya mengembalikannya, memilih 160 karakter, kembali lagi dan pilih 80.

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

Kalau-kalau Anda bertanya-tanya, mengapa ada revprogram.

Kritik:

  • Perintah pertama dimasukkan, sehingga menggerakkan garis tetap. Nah - hanya latihan numerik untuk memilih baris ke-3 terakhir atau sesuatu. Saya bekerja terutama di jendela yang berbeda.
  • Tidak semua orang memiliki layar 80x50. Ya, kita tahu. Ada $ COLUMNS dan $ ROWS untuk kesenangan Anda.
  • Output tidak selalu di bagian bawah. Cangkang baru dan muda mungkin ada di baris atas. Yah - sesederhana itu: Evaluasi shell apa yang sedang berjalan. Prompt yang digunakan. Lakukan deteksi cepat dan temukan baris terakhir dengan prompt shell. Baris sebelum (atau 2. sebelumnya) harus berisi direktori.

Diagram pertama dibuat dengan explan.py

Pengguna tidak diketahui
sumber
+1, membuat saya melakukannyaalias tee2tty='tee $(readlink /proc/$$/fd/1)'
Tobias Kienzler
7

Coba ini:

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

Jadi, uh, inilah jawabannya:

Jika Anda menjalankan di bawah X, pilih output yang Anda inginkan dengan mouse untuk menyalinnya, lalu klik tengah untuk menempelkannya.

Jika Anda menjalankan konsol teks, Anda dapat melakukan hal serupa dengan gpm .

mattdm
sumber
1
+1 - jawaban yang bagus! Anda dapat mencapai hal yang sama, bahkan jika Anda tidak menjalankan X, dengan menggunakan layar GNU ( gnu.org/software/screen ).
simon
1
Tampaknya begitu jelas sehingga saya ragu untuk mengatakannya. Tapi semua orang sibuk menjadi pintar. :)
mattdm
itu satu-satunya jawaban di sini yang memungkinkan OP untuk menggunakan kembali baris terakhir - semuanya memerlukan menjalankan perintah lagi, yang bisa di mana saja antara benar-benar tidak relevan dan bencana :) Tapi OP memang mengatakan menggunakan kembali .
simon
@simon: Sebenarnya, jawabanku tidak. Glenn juga tidak.
Mikel
@Mikel: Benar, tetapi mereka mengharuskan Anda melakukan sesuatu sebelumnya, atau benar pertama kali.
mattdm
1

(Sayangnya, ini bukan jawaban yang berfungsi, tetapi masih sesuatu yang aneh. Seseorang yang tertarik bisa mencoba menyelesaikan penerapan fitur yang akan saya ceritakan.)

Di eshelldalam Emacs, mereka ingin memiliki fitur seperti itu tetapi tidak diimplementasikan secara lengkap (yang tercermin dalam dokumentasi ).

Sebagai contoh:

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

~ $ 

Soalnya, hanya output builtin yang bisa ditangkap ke dalam $$variabel.

Namun, beberapa pemrograman elisp (lih eshell-mark-outputimplementasi di "esh-mode.el"), dan Anda bisa mengimplementasikan fungsi yang "menandai" output terakhir dan mengembalikannya sebagai hasil fungsi; sehingga Anda dapat menggunakan fungsi itu dalam perintah eshell yang Anda minta - fungsi elisp dapat digunakan dalam perintah eshell dengan sintaks elisp yang biasa, yaitu dalam tanda kurung, seperti ini:

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

Jika Anda sadar ingin menggunakan kembali output sebelum menekan Enter, Anda bisa menyimpannya dalam variabel: tambahkan tmp=$(di awal baris dan )di akhir. (Ini menghapus setiap baris kosong di akhir output perintah, dan pada kenyataannya menghapus baris baru akhir; ini jarang penting.)

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

Jika shell Anda adalah ksh atau zsh, inilah fungsi berguna yang dapat Anda gunakan untuk menjadikan ini lebih otomatis. (Tidak ada gunanya dalam bash karena membutuhkan perintah terakhir dalam sebuah pipa untuk dieksekusi di shell induk, yang hanya merupakan kasus di ksh (bukan pdksh) dan zsh.)

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

Gunakan seperti ini:

python -c  |k
cd $kept
Gilles 'SANGAT berhenti menjadi jahat'
sumber
0
cd $(python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()" | tee $(readlink /proc/$$/fd/1))

(membangun jawaban 4485 )

Itu banyak mengetik, jadi buatlah alias:

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

Maka cukup menelepon cd $(python -c ... | tee2tty)

Ini tentu saja mengharuskan Anda sudah tahu apa yang ingin Anda lakukan dengan output tetapi memiliki keuntungan dari memanggil perintah hanya sekali.

Tobias Kienzler
sumber
0
$ cd \`python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()"\`

akan melakukan trik.

Baca di sini untuk detail lebih lanjut: Substitusi perintah .

Yousouser
sumber
1
arumug: bahamat sudah memposting jawaban yang hampir sama . Versi Anda dengan backticks tidak akan selalu berfungsi jika sudah ada backticks dalam perintah.
Gilles 'SO- berhenti bersikap jahat'
0

Ada solusi yang lebih baik:

Cukup cetak !!setelah perintah dieksekusi dan Anda akan mendapatkan output berulang.

Misalnya

masukkan deskripsi gambar di sini

Asli:

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

Tebe
sumber
!!tidak mengulangi hasil dari perintah terakhir, itu menjalankan kembali perintah terakhir. Jika jot -r 1 0 1000mengembalikan nomor acak tunggal antara 0 dan 1000, maka setelah menjalankan perintah itu sekali dan mendapatkan 539, menjalankan !!kemungkinan besar akan memberikan beberapa nomor lainnya. !!mungkin juga tidak diinginkan jika perintah sebelumnya membutuhkan waktu yang signifikan untuk dijalankan, atau mengulangi operasi yang tidak boleh diulang (seperti mengubah file).
Caleb
1
tangkapan bagus. Meskipun ada cara yang lebih mudah untuk membuktikan bahwa saya salah: echo $ RANDOM; !!
Tebe
Manis - tidak tahu tentang itu! Terima kasih.
Caleb