Auswerten einer Zeichenfolge im Shell-Skript

8

Ich folge dieser Bash-Shell-Skriptanleitung:

Im Abschnitt Numerische Vergleiche wird ein Beispiel angeführt:

anny > num=`wc -l work.txt`

anny > echo $num
201

anny > if [ "$num" -gt "150" ]
More input> then echo ; echo "you've worked hard enough for today."
More input> echo ; fi

Was oben zu passieren scheint, ist, dass wir eine Folge von Befehlen in einer Bash-Variablen speichern und dann das Echo für die Variable aufrufen. Was zu passieren scheint, ist, dass die Zeichenfolge ausgewertet und der Befehl wc ausgeführt wird und die Zeilenanzahl an das steuernde Terminal zurückgibt.

Ok, also starte ich mein Terminal in Ubuntu 12.04 und versuche etwas Ähnliches:

$ touch sample.txt && echo "Hello World" > sample.txt
$ cat sample.txt
Hello World
$ num='wc -l sample.txt'
echo $num
wc -l sample.txt

Warten Sie eine Sekunde, die die Zeichenfolge nicht ausgewertet hat, und geben Sie die Zeilenanzahl zurück. Das hat die Zeichenfolge nur zum Terminal zurückgesendet. Warum habe ich unterschiedliche Ergebnisse erzielt?

John Merlino
quelle
Beachten Sie, dass num niemals die Zeichenfolge zugewiesen wird wc -l work.txt, sondern die Nummer 201.
ignis
Verwandte Ressource: 3.5.4 Befehlsersetzung im Bash-Referenzhandbuch .
Eliah Kagan

Antworten:

2

Sie müssen Backticks verwenden, um den Ausdruck auszuwerten.

$ num=`wc -l sample.txt`
$ echo $num
1 sample.txt

Wenn Sie nur "1" in der Ausgabe sehen möchten, verwenden Sie den Befehl

$ num=`cat sample.txt | wc -l`
$ echo $num
1

Und funktioniert auch:

$ num=`wc -l < sample.txt`
$ echo $num
1

Weitere Informationen finden Sie unter Unterschiede zwischen Doppelzitaten, Einzelzitaten und Backticks in der Befehlszeile.

Danatela
quelle
Irgendeine Idee, warum ich '1 sample.txt' bekomme und nicht nur die Nummer '1'?
John Merlino
So funktioniert wcBefehl. Versuchen Sie es cat sample.txt | wc -l.
Danatela
wc -l zeigt die Anzahl der in einer Datei vorhandenen Zeilen zusammen mit dem Dateinamen an.
Avinash Raj
5

Bitte beachten Sie dieses Symbol:

'

Einfaches Zitat

   Enclosing characters in single quotes preserves the  literal  value  of
   each character within the quotes.  A single quote may not occur between
   single quotes, even when preceded by a backslash.

und

`

Backquote

   Command substitution allows the output of a command to replace the com
   mand name.  There are two forms:

          $(command)
   or
          `command`

   Bash performs the expansion by executing command and replacing the com
   mand  substitution  with  the  standard output of the command, with any
   trailing newlines deleted.

Das Backquote gibt also das Ergebnis des Befehls an die Standardausgabe zurück. Deswegen

`wc -l sample.txt`

Gibt die Ergebnisse des Befehls zurück, während

'wc -l sample.txt'

Geben Sie einfach "wc -l sample.txt" wie gewohnt zurück

Betrachten Sie dies als Beispiel:

$ A='wc -l /proc/mounts'
$ B=`wc -l /proc/mounts`
$ C=$(wc -l /proc/mounts)

Und jetzt alle drei Variablen wiedergeben:

$ echo $A
wc -l /proc/mounts
$ echo $B
35 /proc/mounts
$ echo $C
35 /proc/mounts
c0rp
quelle
4

Wenn Sie die Ausgabe eines Befehls in einer Variablen erfassen möchten, müssen Sie entweder Backticks verwenden ``oder den Befehl in Folgendes einschließen $():

$ d=$(date)
$ echo "$d"
Mon Mar 17 10:22:25 CET 2014
$ d=`date`
$ echo "$d"
Mon Mar 17 10:22:25 CET 2014

Beachten Sie, dass die Zeichenfolge zum Zeitpunkt der Variablendeklaration tatsächlich ausgewertet wird und nicht, wenn Sie sie wiedergeben. Der Befehl wird tatsächlich innerhalb der $()oder Backticks ausgeführt und die Ausgabe dieses Befehls wird als Wert der Variablen gespeichert.

Im Allgemeinen sollten Sie immer $()anstelle von Backticks verwenden, die veraltet sind und nur aus Kompatibilitätsgründen und viel eingeschränkter vorhanden sind. Sie können beispielsweise keine Befehle in Backticks verschachteln, aber Sie können mit $():

$ echo $(date -d $(echo yesterday))
Sun Mar 16 10:26:07 CET 2014

In diesem Thread zu U & L finden Sie weitere Informationen dazu, warum ``dies vermieden werden sollte.

Terdon
quelle
1
Ich bin damit einverstanden Skripte sollten lieber $( )zu ` `. Aber wie wag sagt , einfache Anführungszeichen tun Nest. echo $(date -d $(echo yesterday))wird echo `date -d \`echo yesterday\``; echo $(echo $(date -d $(echo yesterday)))wird echo `echo \`date -d \\\`echo yesterday\\\`\``. Ich sage, dies widerlegt Ihre These nicht, sondern stärkt sie : Entkommene interne Backquotes machen die ` `Syntax leistungsfähiger als oft zugegeben, aber eine spezielle Behandlung von \ist seltsam, überraschend und schwer zu begründen. Mit dem, $( )was Sie sehen, bekommen Sie normalerweise.
Eliah Kagan