Czy dane wyjściowe polecenia Bash są przechowywane w jakimkolwiek rejestrze? Np. Coś podobnego do $?
przechwytywania wyjścia zamiast statusu wyjścia.
Mógłbym przypisać dane wyjściowe do zmiennej z:
output=$(command)
ale to więcej pisania ...
Czy dane wyjściowe polecenia Bash są przechowywane w jakimkolwiek rejestrze? Np. Coś podobnego do $?
przechwytywania wyjścia zamiast statusu wyjścia.
Mógłbym przypisać dane wyjściowe do zmiennej z:
output=$(command)
ale to więcej pisania ...
Odpowiedzi:
Możesz użyć $(!!)
do przeliczenia (nie ponownego użycia) wyniku ostatniego polecenia.
!!
Na własnych wykonuje ostatnie polecenie.
$ echo pierre
pierre
$ echo my name is $(!!)
echo my name is $(echo pierre)
my name is pierre
$(your_cmd)
za pomocą grawitacji: `your_cmd`
Zgodnie z instrukcją Gnu Bash są one funkcjonalnie identyczne. Oczywiście jest to również przedmiotem ostrzeżenia podniesionego przez @memecs
git diff $(!!)
gdzie poprzednie polecenie było find
wywołaniem.
$()
zamiast graweru. Ale prawdopodobnie nie ma nad czym stracić snu. github.com/koalaman/shellcheck/wiki/SC2006
$()
.
Odpowiedź brzmi nie. Bash nie przydziela żadnego wyjścia do żadnego parametru ani żadnego bloku w swojej pamięci. Ponadto możesz uzyskać dostęp do Bash tylko poprzez dozwolone operacje interfejsu. Prywatne dane Bash nie są dostępne, chyba że je zhakujesz.
Jednym ze sposobów jest użycie trap DEBUG
:
f() { bash -c "$BASH_COMMAND" >& /tmp/out.log; }
trap 'f' DEBUG
Teraz stdout i stderr ostatnio wykonywanego polecenia będą dostępne w /tmp/out.log
Jedynym minusem jest to, że wykona polecenie dwukrotnie: raz, aby przekierować wyjście i błąd do /tmp/out.log
i raz normalnie. Prawdopodobnie istnieje również sposób, aby temu zapobiec.
rm -rf * && cd ..
, nie tylko bieżący katalog, ale także katalog nadrzędny zostanie usunięty? takie podejście wydaje mi się bardzo niebezpieczne
trap '' DEBUG
Jeśli korzystasz z komputera Mac i nie masz nic przeciwko przechowywaniu wyników w schowku zamiast zapisywania w zmiennej, możesz użyć pbcopy i pbpaste jako obejścia.
Na przykład, zamiast robić to, aby znaleźć plik i porównać jego zawartość z innym plikiem:
$ find app -name 'one.php'
/var/bar/app/one.php
$ diff /var/bar/app/one.php /var/bar/two.php
Możesz to zrobić:
$ find app -name 'one.php' | pbcopy
$ diff $(pbpaste) /var/bar/two.php
Ciąg /var/bar/app/one.php
znajduje się w schowku po uruchomieniu pierwszego polecenia.
Nawiasem mówiąc, pb in pbcopy
i pbpaste
oznacza pasteboard, synonim schowka.
$ find app -name 'one.php' | xclip $ diff $(xclip -o) /var/bar/two.php
pbpaste
razem z zastępowaniem poleceń.
Zainspirowany odpowiedzią anubhavy, która moim zdaniem jest nie do zaakceptowania, ponieważ uruchamia każde polecenie dwukrotnie.
save_output() {
exec 1>&3
{ [ -f /tmp/current ] && mv /tmp/current /tmp/last; }
exec > >(tee /tmp/current)
}
exec 3>&1
trap save_output DEBUG
W ten sposób wynik ostatniego polecenia znajduje się w / tmp / last, a polecenie nie jest wywoływane dwukrotnie.
grep
lub git diff
+1
Tak jak powiedział konsolebox, musiałbyś włamać się do samego basha. Oto całkiem dobry przykład, jak można to osiągnąć. Repozytorium stderred (w rzeczywistości przeznaczone do kolorowania standardowego wyjścia) zawiera instrukcje, jak je zbudować.
I spróbowaliśmy: definiowanie jakiegoś nowego deskryptora pliku wewnątrz .bashrc
jak
exec 41>/tmp/my_console_log
(liczba jest dowolna) i stderred.c
odpowiednio zmodyfikuj , aby treść również została zapisana na fd 41. W pewnym sensie działała, ale zawiera mnóstwo bajtów NUL, dziwne formatowanie i jest w zasadzie danymi binarnymi, nieczytelnymi. Może ktoś, kto dobrze rozumie C, mógłby to wypróbować.
Jeśli tak, wszystko, co jest potrzebne do uzyskania ostatniej wydrukowanej linii, to tail -n 1 [logfile]
.
Tak, po co za każdym razem pisać dodatkowe wiersze. Możesz przekierować z powrotem na wejście, ale wyjście na wejście (1> & 0) nie działa. Nie będziesz też chciał wielokrotnie pisać funkcji w każdym pliku dla tego samego.
Jeśli nigdzie nie eksportujesz plików i zamierzasz używać ich tylko lokalnie, możesz ustawić w Terminalu deklarację funkcji. Musisz dodać funkcję w ~/.bashrc
pliku lub w ~/.profile
pliku. W drugim przypadku musisz włączyć Run command as login shell
z Edit>Preferences>yourProfile>Command
.
Utwórz prostą funkcję, powiedz:
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<&-
}
W głównym skrypcie:
#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 zapisuje zmienną nawet poza poprzednim zakresem:
#get previous command outputs in arr
for((i=0; i<${#arr[@]}; i++)); do echo ${arr[i]}; done
Takiego, którego używam od lat.
.bashrc
lub .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
Zwykle dodaję | cap
na końcu wszystkich moich poleceń. W ten sposób, gdy stwierdzę, że chcę przetworzyć tekst na wyjściu wolno działającego polecenia, zawsze mogę go pobrać res
.
cat -
w cap () { cat - | tee /tmp/capture.out}
tutaj? Czy cap () { tee /tmp/capture.out }
pojawiają się jakieś problemy, których mi brakuje?
cat - | cat - | cat -
wcześniej, żeby było ciekawiej? 😉 Naprawię to po przetestowaniu, aby upewnić się, że to naprawdę spandrel
Nie jestem pewien, do czego to potrzebujesz, więc ta odpowiedź może nie być odpowiednia. Zawsze możesz zapisać wynik polecenia:, netstat >> output.txt
ale nie sądzę, że tego właśnie szukasz.
Istnieją oczywiście opcje programowania; możesz po prostu uzyskać program, który przeczyta powyższy plik tekstowy po uruchomieniu tego polecenia i skojarzy go ze zmienną, aw Ruby, moim wybranym języku, możesz utworzyć zmienną z wyjścia polecenia za pomocą `` lewych apostrofów '':
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
Umieść to w pliku .rb i uruchom: ruby file.rb
a utworzy zmienną z polecenia i pozwoli na manipulowanie nią.
Mam pomysł, którego nie mam czasu na natychmiastową realizację.
Ale co, jeśli zrobisz coś takiego:
$ 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!
Mogą wystąpić problemy z buforowaniem we / wy. Plik może również stać się zbyt duży. Trzeba byłoby znaleźć rozwiązanie tych problemów.
Jeśli nie chcesz ponownie obliczyć poprzedniego polecenia, możesz utworzyć makro, które skanuje bieżący bufor terminala, próbuje odgadnąć -supposed- wynik ostatniego polecenia, kopiuje je do schowka i na koniec wpisuje do terminala.
Może być używany do prostych poleceń, które zwracają pojedynczą linię wyjścia (testowane na Ubuntu 18.04 z gnome-terminal
).
Zainstalować następujące narzędzia: xdootool
, xclip
,ruby
W gnome-terminal
podróży do Preferences -> Shortcuts -> Select all
i ustawić go Ctrl+shift+a
.
Utwórz następujący skrypt 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
W ustawieniach klawiatury dodaj następujący skrót klawiaturowy:
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 '
Powyższy skrót: