L'output di un comando Bash è memorizzato in un registro? Ad esempio qualcosa di simile alla $?
cattura dell'output anziché allo stato di uscita.
Potrei assegnare l'output a una variabile con:
output=$(command)
ma è più digitando ...
L'output di un comando Bash è memorizzato in un registro? Ad esempio qualcosa di simile alla $?
cattura dell'output anziché allo stato di uscita.
Potrei assegnare l'output a una variabile con:
output=$(command)
ma è più digitando ...
Risposte:
È possibile utilizzare $(!!)
per ricalcolare (non riutilizzare) l'output dell'ultimo comando.
Da !!
solo esegue l'ultimo comando.
$ echo pierre
pierre
$ echo my name is $(!!)
echo my name is $(echo pierre)
my name is pierre
$(your_cmd)
usando i backtick: `your_cmd`
secondo il manuale di Gnu Bash sono funzionalmente identici. Naturalmente questo è anche soggetto all'avvertimento lanciato da @memecs
git diff $(!!)
cui il comando precedente era una find
chiamata.
$()
posto dei bastoncini. Ma probabilmente niente da perdere. github.com/koalaman/shellcheck/wiki/SC2006
$()
.
La risposta è no. Bash non alloca alcun output a nessun parametro o blocco nella sua memoria. Inoltre, puoi accedere a Bash solo tramite le sue operazioni di interfaccia consentite. I dati privati di Bash non sono accessibili a meno che non vengano hackerati.
Un modo per farlo è usando trap DEBUG
:
f() { bash -c "$BASH_COMMAND" >& /tmp/out.log; }
trap 'f' DEBUG
Ora il comando stdout e stderr eseguiti più di recente saranno disponibili in /tmp/out.log
L'unico inconveniente è che eseguirà un comando due volte: una volta per reindirizzare l'output e l'errore verso /tmp/out.log
e una volta normalmente. Probabilmente esiste un modo per prevenire anche questo comportamento.
rm -rf * && cd ..
, non solo la directory corrente, ma anche la directory principale verrà cancellata ?? questo approccio mi sembra molto pericoloso
trap '' DEBUG
Se sei su Mac e non ti dispiace archiviare il tuo output negli appunti invece di scrivere su una variabile, puoi usare pbcopy e pbpaste come soluzione alternativa.
Ad esempio, invece di farlo per trovare un file e diffrarne il contenuto con un altro file:
$ find app -name 'one.php'
/var/bar/app/one.php
$ diff /var/bar/app/one.php /var/bar/two.php
Potresti farlo:
$ find app -name 'one.php' | pbcopy
$ diff $(pbpaste) /var/bar/two.php
La stringa /var/bar/app/one.php
è negli Appunti quando si esegue il primo comando.
A proposito, pb in pbcopy
e pbpaste
sta per pasteboard, un sinonimo di appunti.
$ find app -name 'one.php' | xclip $ diff $(xclip -o) /var/bar/two.php
pbpaste
insieme alla sostituzione dei comandi.
Ispirato dalla risposta di Anubhava, che a mio avviso non è accettabile in quanto esegue ogni comando due volte.
save_output() {
exec 1>&3
{ [ -f /tmp/current ] && mv /tmp/current /tmp/last; }
exec > >(tee /tmp/current)
}
exec 3>&1
trap save_output DEBUG
In questo modo l'output dell'ultimo comando è in / tmp / last e il comando non viene chiamato due volte.
grep
o git diff
+1 comunque
Come ha detto Konsolebox, dovresti hackerare Bash stesso. Ecco un buon esempio di come si potrebbe raggiungere questo obiettivo. Il repository stderred (in realtà pensato per colorare lo stdout) fornisce istruzioni su come costruirlo.
Ci ho provato: definire alcuni nuovi descrittori di file all'interno di .bashrc
like
exec 41>/tmp/my_console_log
(numero è arbitrario) e modificare stderred.c
di conseguenza in modo che il contenuto viene scritto anche per fd 41. tipo di lavorato, ma contiene un sacco di NUL byte, formattazioni strani ed è fondamentalmente dati binari, non leggibile. Forse qualcuno con una buona comprensione di C potrebbe provarlo.
In tal caso, tutto ciò che è necessario per ottenere l'ultima riga stampata è tail -n 1 [logfile]
.
Sì, perché digitare righe extra ogni volta concordato. È possibile reindirizzare restituito all'input, ma l'output all'input (1> & 0) è nope. Inoltre non vorrai scrivere una funzione ancora e ancora in ogni file per lo stesso.
Se non si esportano i file da nessuna parte e si intende utilizzarli solo localmente, è possibile impostare Terminale nella configurazione della dichiarazione delle funzioni. Devi aggiungere la funzione nel ~/.bashrc
file o nel ~/.profile
file. Nel secondo caso, è necessario abilitare Run command as login shell
da Edit>Preferences>yourProfile>Command
.
Crea una funzione semplice, ad esempio:
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<&-
}
Nella sceneggiatura principale:
#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 salva la variabile anche al di fuori dell'ambito precedente:
#get previous command outputs in arr
for((i=0; i<${#arr[@]}; i++)); do echo ${arr[i]}; done
Uno che ho usato per anni.
.bashrc
o .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
Tendo ad aggiungere | cap
alla fine di tutti i miei comandi. In questo modo, quando trovo che voglio eseguire l'elaborazione del testo sull'output di un comando a esecuzione lenta, posso sempre recuperarlo con res
.
cat -
a cap () { cat - | tee /tmp/capture.out}
qui? Fa cap () { tee /tmp/capture.out }
incorrere alcun inconveniente mi manca?
cat - | cat - | cat -
prima solo per renderlo più interessante? 😉 Risolverò una volta che ho provato per assicurarsi che sia davvero un spandrel
Non sono sicuro di cosa ti serva, quindi questa risposta potrebbe non essere pertinente. Puoi sempre salvare l'output di un comando:, netstat >> output.txt
ma non credo sia quello che stai cercando.
Esistono ovviamente opzioni di programmazione; potresti semplicemente ottenere un programma per leggere il file di testo sopra dopo che quel comando è stato eseguito e associarlo a una variabile, e in Ruby, la mia lingua preferita, puoi creare una variabile fuori dal comando usando 'backtick':
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
Inseriscilo in un file .rb ed eseguilo: ruby file.rb
e creerà una variabile fuori dal comando e ti permetterà di manipolarlo.
Ho un'idea che non ho tempo per provare a implementare immediatamente.
Ma cosa succede se fai qualcosa del genere:
$ 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!
Potrebbero esserci problemi con il buffering IO. Inoltre, il file potrebbe diventare troppo grande. Si dovrebbe trovare una soluzione a questi problemi.
Penso che usare il comando script potrebbe essere d'aiuto. Qualcosa di simile a,
script -c bash -qf fifo_pid
Utilizzo delle funzionalità di bash da impostare dopo l'analisi.
Se non si desidera ricalcolare il comando precedente, è possibile creare una macro che esegue la scansione del buffer del terminale corrente, provare a indovinare l'output fornito dall'ultimo comando, copiarlo negli Appunti e infine digitarlo sul terminale.
Può essere utilizzato per semplici comandi che restituiscono una singola riga di output (testato su Ubuntu 18.04 con gnome-terminal
).
Installare i seguenti strumenti: xdootool
, xclip
,ruby
In gnome-terminal
vai a Preferences -> Shortcuts -> Select all
e impostalo su Ctrl+shift+a
.
Crea il seguente script ruby:
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
Nelle impostazioni della tastiera aggiungi la seguente scorciatoia da tastiera:
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 '
La scorciatoia sopra: