Ich verwende sh (nicht bash/csh) unter FreeBSD 11 und verstehe Folgendes nicht:
In der Konsole
Befehl:zpool status -v
Ergebnis:
pool: My_pool
state: ONLINE
status: One or more devices is currently being resilvered. The pool will
continue to function, possibly in a degraded state.
action: Wait for the resilver to complete.
Zeilenweises Aufteilen und zeilenweises Drucken in einem Skript:
#!/bin/sh
zp="$(zpool status -v)"
for line in $zp; do
echo "$line%"
done
Ergebnis:
pool:%
My_pool%
state:%
ONLINE%
status:%
One%
or%
more%
devices%
is%
currently%
being%
resilvered.%
The%
pool%
will%
continue%
to%
function,%
possibly%
in%
a%
degraded%
state.%
action:%
Wait%
Nach allem, was ich herausfinden kann, ist die von mir verwendete Syntax für sh korrekt und sollte jeweils eine Zeile und nicht jeweils ein Wort lesen.
Was vermisse ich?
Antwort1
Ich bin verwirrt über das, was Sie gefunden haben. Die von Ihnen verwendete Syntax ist für sh korrekt und teilt bei Leerzeichen, nicht nur bei Zeilenumbrüchen. Dies ist ausführlich dokumentiert. Zu denken, dass es bei Zeilenumbrüchen teilt, ist kein weit verbreiteter Irrtum. (Nicht zu verstehen, dass es teilt, ist ein weit verbreiteter Irrtum.)
Genauer gesagt wird das Weglassen einer Variablenerweiterung ohne Anführungszeichen, wie in $zp
, manchmal als „Split+Glob“-Operator bezeichnet. Er bewirkt Folgendes:
- Übernehmen Sie den Wert der Variablen. Das ist eine Zeichenfolge.
- Teilen Sie diesen Wert an jedem Feldtrennzeichen auf. Ein Feldtrennzeichen ist ein Zeichen, das im Wert der Variable vorkommt
IFS
; standardmäßig enthält diese Variable einLeerzeichen, Tabulator und Zeilenumbruch(Dieser Standard wird auch verwendet, wenn die Variable nicht gesetzt ist.) Das Ergebnis ist eine Liste von Zeichenfolgen. - Betrachten Sie jedes Element der Liste als Platzhaltermuster (Glob). Wenn es mit einem oder mehreren Dateinamen übereinstimmt, wird dieses Element durch die Liste der übereinstimmenden Dateinamen ersetzt. Andernfalls wird das Element unverändert gelassen.
Wenn das Verzeichnis beispielsweise Dateien mit den Namen foo
, bar
und enthält baz
, druckt das folgende Skript drei Zeilen: a*
, bar
und baz
.
zq='a* b*'
for word in $zq; do echo "$word"; done
Wenn Sie eine Zeichenfolge an Zeilenumbrüchen teilen möchten, können Sie dies tun, indem Sie IFS
einen Zeilenumbruch festlegen und die Platzhaltererweiterung deaktivieren.
#!/bin/sh
set -f
IFS='
'
zq=…
for line in $zq; do
…
done
Dies gilt für alle sh- und csh-Varianten.
Antwort2
Um Zeilen zu lesen, verwenden Sie die in Ihrer Shell integriertelesenFunktion,
$Hilfe lesen | Kopf -2
lesen: lesen [-ers] [-u fd] [-t Timeout] [-p Eingabeaufforderung] [-a Array] [-n nchars] [-d delim] [Name ...]
Eine Zeile wird von der Standardeingabe gelesen, oder vom Dateideskriptor FD, wenn die Option -u angegeben ist
Setzen Sie es in eine while
Schleife ein und voilà, Sie haben die Zeilen:
$ wc -l -w ~/.profile
24 47 /Users/jklowden/.profile
$ for W in $(cat ~/.profile); do echo $W; done | wc -l
47
$ while read L; do echo $L; done < ~/.profile | wc -l
24