Ich habe ein ziemlich einfaches Skript, das ungefähr so aussieht:
#!/bin/bash
VAR1="$1"
MOREF='sudo run command against $VAR1 | grep name | cut -c7-'
echo $MOREF
Wenn ich dieses Skript über die Befehlszeile ausführe und ihm die Argumente übergebe, erhalte ich keine Ausgabe. Wenn ich jedoch die in der $MOREF
Variablen enthaltenen Befehle ausführe , kann ich eine Ausgabe erhalten.
Wie kann man die Ergebnisse eines Befehls, der in einem Skript ausgeführt werden muss, in einer Variablen speichern und diese Variable dann auf dem Bildschirm ausgeben?
bash
shell
command-line
John
quelle
quelle
echo
ist die Variable eine nutzlose Verwendungecho
, und eine nutzlose Verwendung von Variablen.Antworten:
Zusätzlich zu Backticks
`command`
kann die Befehlssubstitution mit$(command)
oder erfolgen"$(command)"
, was meiner Meinung nach leichter zu lesen ist und das Verschachteln ermöglicht.Quoting (
"
) ist wichtig, um mehrzeilige Variablenwerte beizubehalten . Es ist auf der rechten Seite einer Zuweisung optional, da keine Wortaufteilung durchgeführt wird und daherOUTPUT=$(ls -1)
gut funktioniert.quelle
echo
Befehl durch Zeichenfolgen aufgeteilt und durch Glob erweitert werden .${OUTPUT}foo
. Sie sind auch erforderlich, wenn Inline-String-Operationen für die Variable ausgeführt werden, z. B.${OUTPUT/foo/bar}
Der richtige Weg ist
Wenn Sie ein Apostroph verwenden möchten, brauchen Sie es
`
nicht'
. Dieses Zeichen wird "Backticks" (oder "schwerwiegender Akzent") genannt.So was:
quelle
echo
.$()
funktioniert. Konnte nicht behoben werden, bis ich diese Seite sah.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
Meistens kompatibel, zweiter Weg
Da die Verschachtelung schwer werden könnte, wurde hierfür eine Klammer implementiert
Verschachtelte Probe:
Lesen von mehr als einer Variablen (mit Bashisms )
Wenn ich nur einen verwendeten Wert möchte :
Sie konnten eine Array- Variable sehen:
Dann:
Aber ich bevorzuge das:
Die erste überspringt
read foo
nur die Kopfzeile, aber in nur einem Befehl werden 7 verschiedene Variablen ausgefüllt:Oder auch:
... funktioniert auch mit assoziativen Arrays :
read foo disk[total] disk[used] ...
Beispielfunktion zum Auffüllen einiger Variablen:
Hinweis:
declare
Zeile ist nicht erforderlich, nur zur besseren Lesbarkeit.Über
sudo cmd | grep ... | cut ...
(Bitte vermeiden Sie nutzlos
cat
! Das ist also nur eine Gabel weniger: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 :Und mit Bashisms :
Aber für viele Aktionen, hauptsächlich für kleine Dateien, könnte Bash die Arbeit selbst erledigen:
oder
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
oder
Dies funktioniert gut, aber viele Gabeln laufen zu lassen ist schwer und langsam.
Und Befehle mögen
date
undbc
könnten viele Operationen machen, Zeile für Zeile !!Sehen:
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:
(Natürlich, FD
5
und6
müssen nicht verwendet werden!) ... Von dort aus können Sie diesen Prozess verwenden, indem Sie: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:
Mit dieser Funktion
myBc
können Sie die Hintergrundaufgabe mit einfacher Syntax und für Datum verwenden:Wenn Sie von dort aus einen der Hintergrundprozesse beenden möchten, müssen Sie nur die fd schließen :
was nicht benötigt wird, da alle fd schließen, wenn der Hauptprozess abgeschlossen ist.
quelle
EXISTING_CONTAINER=$(docker ps -a | grep "$(echo $CONTAINER_NAME)")
war die Aussage, nach der ich gesucht habe.echo
; Sie wollen einfachgrep "$CONTAINER_NAME"
tput
als Hintergrundaufgabe für die Farbwiedergabe auf dem Terminal an !kubectl get ns | while read -r line; do echo
$ line | grep Begriff | cut -d '' -f1; done
druckt für jede$line
eine leere Zeile aus und dannbash: xxxx: command not found
. Ich würde jedoch erwarten, dass es nur gedruckt wirdxxx
Wie sie Ihnen bereits angedeutet haben, sollten Sie "Backticks" verwenden.
Die vorgeschlagene Alternative
$(command)
funktioniert ebenfalls und ist auch leichter zu lesen. Beachten Sie jedoch, dass sie nur mit Bash oder KornShell (und von diesen abgeleiteten Shells) gültig ist. Wenn Ihre Skripte also auf verschiedenen Unix-Systemen wirklich portabel sein müssen, sollten Sie dies vorziehen die alte Backticks-Notation.quelle
$()
ist voll kompatibel mit POSIX sh, wie vor über zwei Jahrzehnten standardisiert./bin/sh
Solaris 10 dies immer noch nicht erkennt$(…)
- und AFAIK gilt auch für Solaris 11./bin/sh
istksh93
.$()
in den letzten 10+ Jahren in der POSIX-Shell auf HP-UX verwendet.Ich kenne drei Möglichkeiten:
Funktionen sind für solche Aufgaben geeignet: **
Rufen Sie es auf, indem Sie sagen
func
.Auch eine andere geeignete Lösung könnte eval sein:
Der dritte verwendet Variablen direkt:
Sie können die Ausgabe der dritten Lösung auf gute Weise erhalten:
Und auch auf böse Weise:
quelle
"$var"
gut und$var
böse?Nur um anders zu sein:
quelle
Stellen Sie beim Festlegen einer Variablen sicher, dass Sie vor und / oder nach dem = -Zeichen KEINE Leerzeichen haben . Ich habe buchstäblich eine Stunde damit verbracht, dies herauszufinden und alle Arten von Lösungen auszuprobieren! Das ist nicht cool.
Richtig:
Wird mit dem Fehler "stuff: not found" oder ähnlichem fehlschlagen
quelle
var=value somecommand
Läufesomecommand
mitvar
in seiner Umgebung mit dem Wertvalue
. Somitvar= somecommand
wirdvar
in der Umgebungsomecommand
mit einem leeren Wert (Null-Byte) exportiert .Wenn Sie dies mit mehrzeiligen / mehreren Befehlen tun möchten, können Sie dies tun:
Oder:
Beispiel:
Ausgabe:
Mit heredoc können Sie die Dinge ganz einfach vereinfachen, indem Sie Ihren langen einzeiligen Code in einen mehrzeiligen Code zerlegen. Ein anderes Beispiel:
quelle
bash
innerhalb der Befehlsersetzung? Sie erstellen bereits eine Unterschale durch die Befehlsersetzung selbst. Wenn Sie mehrere Befehle einfügen möchten, trennen Sie diese einfach durch Zeilenumbruch oder Semikolon.output=$(echo first; echo second; ...)
'bash -c "bash -c \"bash -c ...\""'
wäre ähnlich auch "anders"; aber ich verstehe den Sinn davon nicht.ssh
sudo -s
Ausführen von MySQL-Befehlen usw. (anstelle von Bash)variable=$(bash -c 'echo "foo"; echo "bar"')
wieder herausvariable=$(echo "foo"; echo "bar")
- das Dokument hier ist nur ein Zitiermechanismus und fügt nur eine weitere nutzlose Komplikation hinzu.ssh -p $port $user@$domain /bin/bash <<EOF
, um einePseudo-terminal will not be allocated because stdin is not a terminal.
Warnung zu verhindernSie müssen entweder verwenden
$(command-here)
oder
Beispiel
quelle
$()
ist viel besser als Backticks. Siehe: Was ist der Vorteil der Verwendung von $ () anstelle von Backticks in Shell-Skripten?Dies ist eine andere Möglichkeit und eignet sich gut für einige Texteditoren, die nicht in der Lage sind, jeden von Ihnen erstellten komplexen Code korrekt hervorzuheben:
quelle
Sie können Backticks (auch als Akzentgräber bezeichnet) oder verwenden
$()
.Mögen:
Beide haben den gleichen Effekt. Aber OUTPUT = $ (x + 2) ist besser lesbar und das neueste.
quelle
Wenn der Befehl, den Sie ausführen möchten, fehlschlägt, wird die Ausgabe in den Fehlerstrom geschrieben und dann auf der Konsole ausgedruckt.
Um dies zu vermeiden, müssen Sie den Fehlerstrom umleiten:
quelle
Einige mögen dies nützlich finden. Ganzzahlige Werte bei der Variablensubstitution, bei der der Trick in
$(())
doppelten Klammern steht:quelle
for ((...))
scheint eine Schleife besser mit der Schleifenvariablen übereinzustimmen ). Außerdem sollten Sie für Ihre privaten Variablen keinen Großbuchstaben verwenden.ARR=(3 2 4 1);for((N=3,M=3,COUNT=N-1;COUNT < ${#ARR[@]};ARR[COUNT]*=M,COUNT+=N)){ :;}
aber ich stimme @tripleee zu: Ich verstehe nicht, was das dort macht!Hier sind zwei weitere Möglichkeiten:
Bitte denken Sie daran, dass Platz in Bash sehr wichtig ist. Wenn Sie also möchten, dass Ihr Befehl ausgeführt wird, verwenden Sie ihn unverändert, ohne weitere Leerzeichen einzufügen.
Die folgenden Abtretungsempfänger
harshil
zuL
und druckt sie dannIm Folgenden wird die Ausgabe des Befehls
tr
L2 zugewiesen.tr
wird an einer anderen Variablen, L1, betrieben.quelle
$"..."
wahrscheinlich nicht das, was du denkst . 2. Dies ist bereits in Andy Lesters Antwort angegeben.echo ${L1,,}
Downcase oderecho ${L1^^}
Upcase verwenden.