Einige Bash- Tricks, mit denen ich Variablen aus Befehlen setze
2nd Edit 2018-02-12: Eine andere Möglichkeit hinzugefügt, suchen Sie unten nach langfristigen Aufgaben !
2018-01-25 Bearbeiten: Eine Beispielfunktion wurde hinzugefügt (zum Auffüllen von Variablen zur Festplattennutzung).
Erster einfacher, alter und kompatibler Weg
myPi=`echo '4*a(1)' | bc -l`
echo $myPi
3.14159265358979323844
Meistens kompatibel, zweiter Weg
Da die Verschachtelung schwer werden könnte, wurde hierfür eine Klammer implementiert
myPi=$(bc -l <<<'4*a(1)')
Verschachtelte Probe:
SysStarted=$(date -d "$(ps ho lstart 1)" +%s)
echo $SysStarted
1480656334
Lesen von mehr als einer Variablen (mit Bashisms )
df -k /
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/dm-0 999320 529020 401488 57% /
Wenn ich nur einen verwendeten Wert möchte :
array=($(df -k /))
Sie konnten eine Array- Variable sehen:
declare -p array
declare -a array='([0]="Filesystem" [1]="1K-blocks" [2]="Used" [3]="Available" [
4]="Use%" [5]="Mounted" [6]="on" [7]="/dev/dm-0" [8]="999320" [9]="529020" [10]=
"401488" [11]="57%" [12]="/")'
Dann:
echo ${array[9]}
529020
Aber ich bevorzuge das:
{ read foo ; read filesystem size using avail prct mountpoint ; } < <(df -k /)
echo $using
529020
Die erste überspringtread foo
nur die Kopfzeile, aber in nur einem Befehl werden 7 verschiedene Variablen ausgefüllt:
declare -p avail filesystem foo mountpoint prct size using
declare -- avail="401488"
declare -- filesystem="/dev/dm-0"
declare -- foo="Filesystem 1K-blocks Used Available Use% Mounted on"
declare -- mountpoint="/"
declare -- prct="57%"
declare -- size="999320"
declare -- using="529020"
Oder auch:
{ read foo ; read filesystem dsk[{6,2,9}] prct mountpoint ; } < <(df -k /)
declare -p mountpoint dsk
declare -- mountpoint="/"
declare -a dsk=([2]="529020" [6]="999320" [9]="401488")
... funktioniert auch mit assoziativen Arrays :read foo disk[total] disk[used] ...
Beispielfunktion zum Auffüllen einiger Variablen:
#!/bin/bash
declare free=0 total=0 used=0
getDiskStat() {
local foo
{
read foo
read foo total used free foo
} < <(
df -k ${1:-/}
)
}
getDiskStat $1
echo $total $used $free
Hinweis: declare
Zeile ist nicht erforderlich, nur zur besseren Lesbarkeit.
Über sudo cmd | grep ... | cut ...
shell=$(cat /etc/passwd | grep $USER | cut -d : -f 7)
echo $shell
/bin/bash
(Bitte vermeiden Sie nutzlos cat
! Das ist also nur eine Gabel weniger:
shell=$(grep $USER </etc/passwd | cut -d : -f 7)
Alle Rohre ( |
) implizieren Gabeln. Wo ein anderer Prozess ausgeführt werden muss, Zugriff auf Festplatte, Bibliotheksaufrufe usw.
Wenn Sie also sed
für sample verwenden, wird der Unterprozess auf nur eine Gabel beschränkt :
shell=$(sed </etc/passwd "s/^$USER:.*://p;d")
echo $shell
Und mit Bashisms :
Aber für viele Aktionen, hauptsächlich für kleine Dateien, könnte Bash die Arbeit selbst erledigen:
while IFS=: read -a line ; do
[ "$line" = "$USER" ] && shell=${line[6]}
done </etc/passwd
echo $shell
/bin/bash
oder
while IFS=: read loginname encpass uid gid fullname home shell;do
[ "$loginname" = "$USER" ] && break
done </etc/passwd
echo $shell $loginname ...
Weiter über die variable Aufteilung ...
Schauen Sie sich meine Antwort auf Wie teile ich eine Zeichenfolge auf einem Trennzeichen in Bash?
Alternative: Reduzieren von Gabeln durch Verwendung von Hintergrundaufgaben mit langer Laufzeit
2. Änderung 2018-02-12:
Um mehrere Gabeln wie zu verhindern
myPi=$(bc -l <<<'4*a(1)'
myRay=12
myCirc=$(bc -l <<<" 2 * $myPi * $myRay ")
oder
myStarted=$(date -d "$(ps ho lstart 1)" +%s)
mySessStart=$(date -d "$(ps ho lstart $$)" +%s)
Dies funktioniert gut, aber viele Gabeln laufen zu lassen ist schwer und langsam.
Und Befehle mögen date
und bc
könnten viele Operationen machen, Zeile für Zeile !!
Sehen:
bc -l <<<$'3*4\n5*6'
12
30
date -f - +%s < <(ps ho lstart 1 $$)
1516030449
1517853288
Wir könnten also einen lang laufenden Hintergrundprozess verwenden, um viele Jobs zu erledigen, ohne für jede Anforderung einen neuen Fork initiieren zu müssen.
Wir brauchen nur einige Dateideskriptoren und Fifos, um dies richtig zu machen:
mkfifo /tmp/myFifoForBc
exec 5> >(bc -l >/tmp/myFifoForBc)
exec 6</tmp/myFifoForBc
rm /tmp/myFifoForBc
(Natürlich, FD 5
und 6
müssen nicht verwendet werden!) ... Von dort aus können Sie diesen Prozess verwenden, indem Sie:
echo "3*4" >&5
read -u 6 foo
echo $foo
12
echo >&5 "pi=4*a(1)"
echo >&5 "2*pi*12"
read -u 6 foo
echo $foo
75.39822368615503772256
In eine Funktion newConnector
Sie finden meine newConnector
Funktion möglicherweise auf GitHub.Com oder auf meiner eigenen Site (Hinweis auf GitHub: Auf meiner Site befinden sich zwei Dateien. Funktion und Demo sind in einer Datei zusammengefasst, die zur Verwendung bezogen oder nur für die Demo ausgeführt werden kann.)
Stichprobe:
. shell_connector.sh
tty
/dev/pts/20
ps --tty pts/20 fw
PID TTY STAT TIME COMMAND
29019 pts/20 Ss 0:00 bash
30745 pts/20 R+ 0:00 \_ ps --tty pts/20 fw
newConnector /usr/bin/bc "-l" '3*4' 12
ps --tty pts/20 fw
PID TTY STAT TIME COMMAND
29019 pts/20 Ss 0:00 bash
30944 pts/20 S 0:00 \_ /usr/bin/bc -l
30952 pts/20 R+ 0:00 \_ ps --tty pts/20 fw
declare -p PI
bash: declare: PI: not found
myBc '4*a(1)' PI
declare -p PI
declare -- PI="3.14159265358979323844"
Mit dieser Funktion myBc
können Sie die Hintergrundaufgabe mit einfacher Syntax und für Datum verwenden:
newConnector /bin/date '-f - +%s' @0 0
myDate '2000-01-01'
946681200
myDate "$(ps ho lstart 1)" boottime
myDate now now ; read utm idl </proc/uptime
myBc "$now-$boottime" uptime
printf "%s\n" ${utm%%.*} $uptime
42134906
42134906
ps --tty pts/20 fw
PID TTY STAT TIME COMMAND
29019 pts/20 Ss 0:00 bash
30944 pts/20 S 0:00 \_ /usr/bin/bc -l
32615 pts/20 S 0:00 \_ /bin/date -f - +%s
3162 pts/20 R+ 0:00 \_ ps --tty pts/20 fw
Wenn Sie von dort aus einen der Hintergrundprozesse beenden möchten, müssen Sie nur die fd schließen :
eval "exec $DATEOUT>&-"
eval "exec $DATEIN>&-"
ps --tty pts/20 fw
PID TTY STAT TIME COMMAND
4936 pts/20 Ss 0:00 bash
5256 pts/20 S 0:00 \_ /usr/bin/bc -l
6358 pts/20 R+ 0:00 \_ ps --tty pts/20 fw
was nicht benötigt wird, da alle fd schließen, wenn der Hauptprozess abgeschlossen ist.