Apakah output dari perintah Bash disimpan dalam register? Misalnya sesuatu yang mirip dengan $?
menangkap output, bukan status keluar.
Saya bisa menetapkan output ke variabel dengan:
output=$(command)
tapi itu lebih banyak mengetik ...
Apakah output dari perintah Bash disimpan dalam register? Misalnya sesuatu yang mirip dengan $?
menangkap output, bukan status keluar.
Saya bisa menetapkan output ke variabel dengan:
output=$(command)
tapi itu lebih banyak mengetik ...
Jawaban:
Anda dapat menggunakan $(!!)
untuk menghitung ulang (tidak menggunakan kembali) output dari perintah terakhir.
The !!
sendiri menjalankan perintah terakhir.
$ echo pierre
pierre
$ echo my name is $(!!)
echo my name is $(echo pierre)
my name is pierre
$(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
git diff $(!!)
mana perintah sebelumnya adalah find
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.
Salah satu cara melakukannya adalah dengan menggunakan trap DEBUG
:
f() { bash -c "$BASH_COMMAND" >& /tmp/out.log; }
trap 'f' 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.
rm -rf * && cd ..
, tidak hanya direktori saat ini, tetapi juga direktori induk akan dihapus ?? pendekatan ini tampaknya sangat berbahaya bagi saya
trap '' 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:
$ find app -name 'one.php'
/var/bar/app/one.php
$ diff /var/bar/app/one.php /var/bar/two.php
Anda bisa melakukan ini:
$ find app -name 'one.php' | pbcopy
$ diff $(pbpaste) /var/bar/two.php
Tali /var/bar/app/one.php
ada di clipboard ketika Anda menjalankan perintah pertama.
By the way, pb di pbcopy
dan pbpaste
berdiri untuk karton, sinonim untuk clipboard.
$ 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.
save_output() {
exec 1>&3
{ [ -f /tmp/current ] && mv /tmp/current /tmp/last; }
exec > >(tee /tmp/current)
}
exec 3>&1
trap save_output DEBUG
Dengan cara ini output dari perintah terakhir ada di / tmp / last dan perintah itu tidak dipanggil dua kali.
grep
atau git diff
+1 tetap
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 .bashrc
seperti
exec 41>/tmp/my_console_log
(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]
.
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 mengaktifkan Run command as login shell
dari 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<&-
}
Dalam skrip utama:
#run your command:
cmd="echo hey ya; echo hey hi; printf `expr 10 + 10`'\n' ; printf $((10 + 20))'\n'"
get_prev $cmd
#or simply
get_prev "echo hey ya; echo hey hi; printf `expr 10 + 10`'\n' ; printf $((10 + 20))'\n'"
Bash menyimpan variabel bahkan di luar ruang lingkup sebelumnya:
#get previous command outputs in arr
for((i=0; i<${#arr[@]}; i++)); do echo ${arr[i]}; done
Salah satu yang saya gunakan selama bertahun-tahun.
.bashrc
atau .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 }
$ find . -name 'filename' | cap
/path/to/filename
$ ret
/path/to/filename
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 dengan res
.
cat -
di cap () { cat - | tee /tmp/capture.out}
sini? Apakah cap () { 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 spandrel
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 command
if 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.rb
dan itu akan membuat variabel dari perintah dan memungkinkan Anda untuk memanipulasinya.
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-terminal
buka Preferences -> Shortcuts -> Select all
dan 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:
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: