Anda dapat menyelamatkan diri dari mengetik $(your_cmd)dengan menggunakan backticks: `your_cmd`Menurut manual Gnu Bash, keduanya secara fungsional identik. Tentu saja ini juga tunduk pada peringatan yang diangkat oleh @memecs
Dalam prakteknya, output dari perintah adalah deterministik sehingga saya tidak akan merasa sakit hati untuk mengkomputasi ulang Ini tentu berguna ketika Anda ingin melakukan sesuatu seperti di git diff $(!!)mana perintah sebelumnya adalah finddoa.
@ user2065875 meskipun backticks masih berfungsi di Bash, mereka tidak digunakan lagi $().
kurczynski
87
Jawabannya adalah tidak. Bash tidak mengalokasikan output apa pun ke parameter apa pun atau blok apa pun di memorinya. Selain itu, Anda hanya diizinkan untuk mengakses Bash dengan operasi antarmuka yang diizinkan. Data pribadi Bash tidak dapat diakses kecuali jika Anda meretasnya.
Apakah mungkin untuk memiliki beberapa fungsi 'middleware' bash kustom yang berjalan sebelum setiap perintah, di mana yang dilakukannya hanyalah menyimpan output yang dihasilkan ke sesuatu yang bertindak sebagai clipboard internal (katakanlah, BASH_CLIPBOARD)?
Pat Needham
@ PatNeedham Tidak yakin. Periksa modul yang dapat dimuat. Lihat apakah Anda dapat menulisnya.
konsolebox
11
Salah satu cara melakukannya adalah dengan menggunakan trap DEBUG:
Sekarang stdout dan stderr perintah yang baru saja dieksekusi akan tersedia di /tmp/out.log
Satunya downside adalah bahwa ia akan menjalankan perintah dua kali: sekali untuk mengarahkan output dan kesalahan ke /tmp/out.logdan sekali secara normal. Mungkin ada beberapa cara untuk mencegah perilaku ini juga.
jadi ketika saya mengetik rm -rf * && cd .., tidak hanya direktori saat ini, tetapi juga direktori induk akan dihapus ?? pendekatan ini tampaknya sangat berbahaya bagi saya
phil294
1
Sekarang bagaimana saya membatalkan tindakan ini?
Kartik Chauhan
5
@KartikChauhan: Lakukan sajatrap '' DEBUG
anubhava
7
Jika Anda menggunakan mac, dan tidak keberatan menyimpan output Anda di clipboard alih-alih menulis ke variabel, Anda dapat menggunakan pbcopy dan pbpaste sebagai solusinya.
Sebagai contoh, alih-alih melakukan ini untuk menemukan file dan berbeda isinya dengan file lain:
di linux $ find app -name 'one.php' | xclip $ diff $(xclip -o) /var/bar/two.php
si-mikey
menarik, saya tidak pernah berpikir untuk menggunakan pbpastebersama dengan substitusi perintah.
Sridhar Sarnobat
Bagaimana jika saya melakukan yang pertama dan kemudian menyadari itu tidak efisien, bagaimana saya menghemat waktu komputasi tanpa menjalankan kembali dengan opsi kedua?
NelsonGon
4
Terinspirasi oleh jawaban anubhava, yang menurut saya sebenarnya tidak dapat diterima karena menjalankan setiap perintah dua kali.
Satu kekurangan yang saya temukan pada hal ini adalah bahwa tidak ada perintah Anda yang berpikir bahwa mereka menjalankan tty lagi, yang berarti Anda perlu perhatian khusus untuk mendapatkan kode warna yang berfungsi untuk utilitas seperti grepatau git diff+1 tetap
Marty Neal
2
Seperti yang dikatakan konsolebox, Anda harus meretas bash itu sendiri. Sini adalah contoh yang cukup bagus tentang bagaimana seseorang dapat mencapai ini. Repositori stderred (sebenarnya dimaksudkan untuk mewarnai stdout) memberikan instruksi tentang cara membuatnya.
Aku mencoba memberikannya: Mendefinisikan beberapa di dalam file descriptor baru .bashrcseperti
exec 41>/tmp/my_console_log
(angka berubah-ubah) dan memodifikasi stderred.csesuai sehingga konten juga ditulis ke fd 41. Ini semacam bekerja, tetapi berisi banyak byte NUL, format aneh dan pada dasarnya adalah data biner, tidak dapat dibaca. Mungkin seseorang dengan pemahaman C yang baik bisa mencobanya.
Jika demikian, semua yang diperlukan untuk mendapatkan garis cetakan terakhir adalah tail -n 1 [logfile].
Ya, mengapa mengetik garis ekstra setiap kali setuju. Anda dapat mengarahkan kembali ke input, tetapi output ke input (1> & 0) tidak. Anda juga tidak akan ingin menulis fungsi lagi dan lagi di setiap file untuk hal yang sama.
Jika Anda tidak mengekspor file di mana saja dan bermaksud menggunakannya secara lokal, Anda dapat meminta Terminal mengatur deklarasi fungsi. Anda harus menambahkan fungsi dalam ~/.bashrcfile atau ~/.profilefile. Dalam kasus kedua, Anda harus mengaktifkan Run command as login shelldari Edit>Preferences>yourProfile>Command.
Buat fungsi sederhana, katakan:
get_prev(){# option 1: create an executable with the command(s) and run it
echo $*>/tmp/exe
bash /tmp/exe >/tmp/out
# option 2: if your command is single command (no-pipe, no semi-colons), still it may not run correct in some exceptions#echo `$*` > /tmp/out# return the command(s) outputs line by line
IFS=$(echo -en "\n\b")
arr=()
exec 3</tmp/out
while read -u 3-r line
do
arr+=($line)
echo $line
done
exec 3<&-}
Salah satu yang saya gunakan selama bertahun-tahun.
Skrip (tambahkan ke Anda .bashrcatau .bash_profile)
# capture the output of a command so it can be retrieved with ret
cap (){ tee /tmp/capture.out}# return the output of the most recent command that was captured by cap
ret (){ cat /tmp/capture.out }
Pemakaian
$ find .-name 'filename'| cap
/path/to/filename
$ ret
/path/to/filename
Saya cenderung menambahkan | cappada akhir semua perintah saya. Dengan cara ini ketika saya menemukan saya ingin melakukan pemrosesan teks pada output dari perintah yang berjalan lambat saya selalu dapat mengambilnya dengan res.
Apa gunanya cat -di cap () { cat - | tee /tmp/capture.out}sini? Apakah cap () { tee /tmp/capture.out }ada cegukan yang hilang?
Watson
1
@Watson poin bagus! Saya tidak tahu mengapa saya memilikinya di sana, kemungkinan kebiasaan. Haruskah saya menambahkan cat - | cat - | cat -terlebih dahulu hanya untuk membuatnya lebih menarik? 😉 Saya akan memperbaikinya setelah saya menguji untuk memastikannya benar-benar spandrel
Connor
0
Tidak yakin untuk apa Anda membutuhkannya, jadi jawaban ini mungkin tidak relevan. Anda selalu dapat menyimpan output dari suatu perintah:netstat >> output.txt tapi saya tidak berpikir itu yang Anda cari.
Tentu saja ada opsi pemrograman; Anda bisa mendapatkan program untuk membaca file teks di atas setelah perintah itu dijalankan dan mengaitkannya dengan variabel, dan di Ruby, bahasa pilihan saya, Anda dapat membuat variabel dari output perintah menggunakan 'backticks':
output =`ls`#(this is a comment) create variable out of commandif output.include?"Downloads"#if statement to see if command includes 'Downloads' folder
print "there appears to be a folder named downloads in this directory."else
print "there is no directory called downloads in this file."
end
Stick ini dalam file .rb dan jalankan: ruby file.rbdan itu akan membuat variabel dari perintah dan memungkinkan Anda untuk memanipulasinya.
"Tidak yakin persis apa yang Anda butuhkan untuk ini" Ya, katakan saja Anda (maksud saya, saya ) hanya menjalankan skrip berdurasi panjang, ingin mencari output, dan dengan bodoh lupa mengarahkan ulang output sebelum mengeksekusi. Sekarang saya ingin mencoba untuk memperbaiki kebodohan saya tanpa menjalankan kembali skrip.
jscs
0
Saya punya ide bahwa saya tidak punya waktu untuk mencoba menerapkan segera.
Tetapi bagaimana jika Anda melakukan sesuatu seperti berikut:
$ MY_HISTORY_FILE =`get_temp_filename`
$ MY_HISTORY_FILE=$MY_HISTORY_FILE bash -i 2>&1| tee $MY_HISTORY_FILE
$ some_command
$ cat $MY_HISTORY_FILE
$ # ^You'll want to filter that down in practice!
Mungkin ada masalah dengan buffering IO. Juga file mungkin menjadi terlalu besar. Seseorang harus menemukan solusi untuk masalah-masalah ini.
Jika Anda tidak ingin menghitung ulang perintah sebelumnya, Anda dapat membuat makro yang memindai buffer terminal saat ini, mencoba menebak output -supposed- dari perintah terakhir, menyalinnya ke clipboard dan akhirnya mengetiknya ke terminal.
Ini dapat digunakan untuk perintah sederhana yang mengembalikan satu baris output (diuji pada Ubuntu 18.04 with gnome-terminal).
Menginstal alat berikut: xdootool, xclip,ruby
Di gnome-terminalbuka Preferences -> Shortcuts -> Select alldan setel ke Ctrl+shift+a.
Buat skrip ruby ​​berikut:
cat >${HOME}/parse.rb <<EOF
#!/usr/bin/ruby
stdin = STDIN.read
d = stdin.split(/\n/)
e = d.reverse
f = e.drop_while {|item| item ==""}
g = f.drop_while {|item| item.start_with?"${USER}@"}
h = g[0]
print h
EOF
Dalam pengaturan keyboard, tambahkan pintasan keyboard berikut:
Jawaban:
Anda dapat menggunakan
$(!!)
untuk menghitung ulang (tidak menggunakan kembali) output dari perintah terakhir.The
!!
sendiri menjalankan perintah terakhir.sumber
$(your_cmd)
dengan menggunakan backticks:`your_cmd`
Menurut manual Gnu Bash, keduanya secara fungsional identik. Tentu saja ini juga tunduk pada peringatan yang diangkat oleh @memecsgit diff $(!!)
mana perintah sebelumnya adalahfind
doa.$()
daripada backticks. Tapi mungkin tidak ada ruginya tidur. github.com/koalaman/shellcheck/wiki/SC2006$()
.Jawabannya adalah tidak. Bash tidak mengalokasikan output apa pun ke parameter apa pun atau blok apa pun di memorinya. Selain itu, Anda hanya diizinkan untuk mengakses Bash dengan operasi antarmuka yang diizinkan. Data pribadi Bash tidak dapat diakses kecuali jika Anda meretasnya.
sumber
Salah satu cara melakukannya adalah dengan menggunakan
trap DEBUG
:Sekarang stdout dan stderr perintah yang baru saja dieksekusi akan tersedia di
/tmp/out.log
Satunya downside adalah bahwa ia akan menjalankan perintah dua kali: sekali untuk mengarahkan output dan kesalahan ke
/tmp/out.log
dan sekali secara normal. Mungkin ada beberapa cara untuk mencegah perilaku ini juga.sumber
rm -rf * && cd ..
, tidak hanya direktori saat ini, tetapi juga direktori induk akan dihapus ?? pendekatan ini tampaknya sangat berbahaya bagi sayatrap '' DEBUG
Jika Anda menggunakan mac, dan tidak keberatan menyimpan output Anda di clipboard alih-alih menulis ke variabel, Anda dapat menggunakan pbcopy dan pbpaste sebagai solusinya.
Sebagai contoh, alih-alih melakukan ini untuk menemukan file dan berbeda isinya dengan file lain:
Anda bisa melakukan ini:
Tali
/var/bar/app/one.php
ada di clipboard ketika Anda menjalankan perintah pertama.By the way, pb di
pbcopy
danpbpaste
berdiri untuk karton, sinonim untuk clipboard.sumber
$ find app -name 'one.php' | xclip $ diff $(xclip -o) /var/bar/two.php
pbpaste
bersama dengan substitusi perintah.Terinspirasi oleh jawaban anubhava, yang menurut saya sebenarnya tidak dapat diterima karena menjalankan setiap perintah dua kali.
Dengan cara ini output dari perintah terakhir ada di / tmp / last dan perintah itu tidak dipanggil dua kali.
sumber
grep
ataugit diff
+1 tetapSeperti yang dikatakan konsolebox, Anda harus meretas bash itu sendiri. Sini adalah contoh yang cukup bagus tentang bagaimana seseorang dapat mencapai ini. Repositori stderred (sebenarnya dimaksudkan untuk mewarnai stdout) memberikan instruksi tentang cara membuatnya.
Aku mencoba memberikannya: Mendefinisikan beberapa di dalam file descriptor baru
.bashrc
seperti(angka berubah-ubah) dan memodifikasi
stderred.c
sesuai sehingga konten juga ditulis ke fd 41. Ini semacam bekerja, tetapi berisi banyak byte NUL, format aneh dan pada dasarnya adalah data biner, tidak dapat dibaca. Mungkin seseorang dengan pemahaman C yang baik bisa mencobanya.Jika demikian, semua yang diperlukan untuk mendapatkan garis cetakan terakhir adalah
tail -n 1 [logfile]
.sumber
Ya, mengapa mengetik garis ekstra setiap kali setuju. Anda dapat mengarahkan kembali ke input, tetapi output ke input (1> & 0) tidak. Anda juga tidak akan ingin menulis fungsi lagi dan lagi di setiap file untuk hal yang sama.
Jika Anda tidak mengekspor file di mana saja dan bermaksud menggunakannya secara lokal, Anda dapat meminta Terminal mengatur deklarasi fungsi. Anda harus menambahkan fungsi dalam
~/.bashrc
file atau~/.profile
file. Dalam kasus kedua, Anda harus mengaktifkanRun command as login shell
dariEdit>Preferences>yourProfile>Command
.Buat fungsi sederhana, katakan:
Dalam skrip utama:
Bash menyimpan variabel bahkan di luar ruang lingkup sebelumnya:
sumber
Solusi yang Sangat Sederhana
Salah satu yang saya gunakan selama bertahun-tahun.
Skrip (tambahkan ke Anda
.bashrc
atau.bash_profile
)Pemakaian
Saya cenderung menambahkan
| cap
pada akhir semua perintah saya. Dengan cara ini ketika saya menemukan saya ingin melakukan pemrosesan teks pada output dari perintah yang berjalan lambat saya selalu dapat mengambilnya denganres
.sumber
cat -
dicap () { cat - | tee /tmp/capture.out}
sini? Apakahcap () { tee /tmp/capture.out }
ada cegukan yang hilang?cat - | cat - | cat -
terlebih dahulu hanya untuk membuatnya lebih menarik? 😉 Saya akan memperbaikinya setelah saya menguji untuk memastikannya benar-benar spandrelTidak yakin untuk apa Anda membutuhkannya, jadi jawaban ini mungkin tidak relevan. Anda selalu dapat menyimpan output dari suatu perintah:
netstat >> output.txt
tapi saya tidak berpikir itu yang Anda cari.Tentu saja ada opsi pemrograman; Anda bisa mendapatkan program untuk membaca file teks di atas setelah perintah itu dijalankan dan mengaitkannya dengan variabel, dan di Ruby, bahasa pilihan saya, Anda dapat membuat variabel dari output perintah menggunakan 'backticks':
Stick ini dalam file .rb dan jalankan:
ruby file.rb
dan itu akan membuat variabel dari perintah dan memungkinkan Anda untuk memanipulasinya.sumber
Saya punya ide bahwa saya tidak punya waktu untuk mencoba menerapkan segera.
Tetapi bagaimana jika Anda melakukan sesuatu seperti berikut:
Mungkin ada masalah dengan buffering IO. Juga file mungkin menjadi terlalu besar. Seseorang harus menemukan solusi untuk masalah-masalah ini.
sumber
Saya pikir menggunakan perintah skrip mungkin membantu. Sesuatu seperti,
skrip -c bash -qf fifo_pid
Menggunakan fitur bash untuk mengatur setelah parsing.
sumber
Jika Anda tidak ingin menghitung ulang perintah sebelumnya, Anda dapat membuat makro yang memindai buffer terminal saat ini, mencoba menebak output -supposed- dari perintah terakhir, menyalinnya ke clipboard dan akhirnya mengetiknya ke terminal.
Ini dapat digunakan untuk perintah sederhana yang mengembalikan satu baris output (diuji pada Ubuntu 18.04 with
gnome-terminal
).Menginstal alat berikut:
xdootool
,xclip
,ruby
Di
gnome-terminal
bukaPreferences -> Shortcuts -> Select all
dan setel keCtrl+shift+a
.Buat skrip ruby ​​berikut:
Dalam pengaturan keyboard, tambahkan pintasan keyboard berikut:
bash -c '/bin/sleep 0.3 ; xdotool key ctrl+shift+a ; xdotool key ctrl+shift+c ; ( (xclip -out | ${HOME}/parse.rb ) > /tmp/clipboard ) ; (cat /tmp/clipboard | xclip -sel clip ) ; xdotool key ctrl+shift+v '
Pintasan di atas:
sumber