2016-04-27 13 views
1

Ich habe versucht, die Verwendung von IFS zu verstehen, aber es gibt etwas, über das ich keine Informationen finden konnte.Was ist die genaue Verwendung und Bedeutung von "IFS =!"

Mein Beispielcode:

#!/bin/sh 
# (C) 2016 Ergin Bilgin 

IFS=! 
for LINE in $(last -a | sed '$ d') 
do 
    echo $LINE | awk '{print $1}' 
done 
unset IFS 

Ich benutze diesen Code letzte Benutzer Zeile für Zeile zu drucken. Ich verstehe völlig die Verwendung von IFS und in diesem Beispiel, wenn ich Standard-IFS verwende, liest es Wort für Wort innerhalb meiner Schleife. Und wenn ich IFS=! benutze liest es Zeile für Zeile, wie ich es wünsche. Das Problem hier ist, dass ich nichts darüber finden konnte "!" überall. Ich kann mich nicht erinnern, wo ich das gelernt habe. Wenn ich über dasselbe Verhalten google, sehe ich andere Werte, die normalerweise Strings sind.

Also, was bedeutet das "!" und wie es mir das gewünschte Ergebnis gibt?

Dank

+1

Sie können den gesamten Code wahrscheinlich durch 'last -a | ersetzen awk 'NF> 8 {print $ 1}' ' – John1024

Antwort

1

Wie Sie wissen, wenn der Ausgang der last hat ein !, die Skript würde die Eingabezeilen für dieses Zeichen aufteilen.

Das Ausgabeformat last ist nicht standardisiert (z. B. nicht in POSIX), aber Sie werden wahrscheinlich kein System finden, bei dem die erste Spalte etwas anderes als den Namen einer Aktion enthält. Zum Beispiel sehe ich:

tom  pts/8  Wed Apr 27 04:25 still logged in michener.jexium-island.net 
tom  pts/0  Wed Apr 27 04:15 still logged in michener.jexium-island.net 
reboot system boot Wed Apr 27 04:02 - 04:35 (00:33)  3.2.0-4-amd64 
tom  pts/0  Tue Apr 26 16:23 - down (04:56)  michener.jexium-island.net 

weiterhin

reboot system boot Fri Apr 1 15:54 - 19:03 (03:09)  3.2.0-4-amd64 
tom  pts/0  Fri Apr 1 04:34 - down (00:54)  michener.jexium-island.net 

wtmp begins Fri Apr 1 04:34:26 2016 

mit Linux und verschiedenen Datumsformaten, Origination, usw., auf anderen Maschinen.

Durch IFS=! Einstellung setzt das Skript die Feldtrennzeichen auf einen Wert, die unwahrscheinlich ist in der Ausgabe von last auftreten, so dass jede Zeile gelesen wird, in LINE ohne es zu spalten. Normalerweise sind Linien auf Leerzeichen aufgeteilt.

Doch wie Sie die Ausgabe von last normalerweise sehen, nutzt Räume für Spalten zu trennen, und es wird in awk zugeführt, die die Linie ohnehin — mit Leerzeichen teilen. Das Skript kann auf verschiedene Weise vereinfacht werden, z.,:

#!/bin/sh 

for LINE in $(last -a | sed -e '$ d' -e 's/ .*//') 
do  
    echo $LINE 
done 

welche ausreichend (aus dem Beispiel in der Frage ausgehend), wenn die Zahl der Anmeldungen nicht groß genug ist, Ihre Befehlszeile zu überschreiten. Bei der Überprüfung auf Variationen in last Ausgabe, bemerkte ich eine Maschine mit etwa 9800 Zeilen aus mehreren Jahren. (Die anderen üblichen Gründe dafür, keine For-Schleifen zu verwenden, sind in diesem Fall nicht plausibel). Als Rohr:

#!/bin/sh 

last -a | sed -e 's/ .*//' -e '/^$/d' | while IFS= read LINE 
do 
    echo $LINE 
done 

änderte ich den sed Ausdruck (die OP wahrscheinlich von einem Ort kopiert wie Bash - remove the last line from a file), weil es nicht funktioniert.

Schließlich ist die Verwendung der Option -alast unnötig, da alle zusätzlichen Informationen verworfen werden.

+0

[Warum liest du keine Zeilen mit "for"] (http://mywiki.wooledge.org/DontReadLinesWithFor) und [BashFAQ/001] (http: // mywiki .wooledge.org/BashFAQ/001) – anubhava

2

IFS=! lediglich einen nicht vorhandenen Wert für IFS einstellen, so dass Sie Eingang Zeile für Zeile durchlaufen können. Having said, die hier für die Schleife ist nicht zu empfehlen, besser read in einer while Schleife wie folgt zu verwenden ersten Spalte dh Benutzername drucken:

last | sed '$ d' | while read -r u _; do 
    echo "$u" 
done 
Verwandte Themen