
Ich habe seltsame Kommentare zum Posten einer awk
Antwort auf SO erhalten, die diese Funktion verwendet getline
.
Hierist der Link zu dieser Antwort.
Nachdem ich meine Antwort gepostet hatte, kommentierte ein Benutzer Folgendes ( ich kritisiere ihn nicht ) .
Keine gute Lösung, da die Zeilen unabhängig vom Inhalt verbunden werden und bei Bedarf keine weiteren Zeilen verarbeitet werden. Außerdem sollten Sie getline nicht verwenden.
getline
Es besagt, dass wir die Funktion in vermeiden sollten awk
. Meine Fragen sind also:
getline
Ist es sicher , Funktionen in Awk zu verwenden ?- Unter welchen Umständen sollten wir es verwenden, und
getline
unter welchen nicht? - Wenn diese Funktion unerwartete Ergebnisse produziert, warum reichen wir dann keinen Fehlerbericht ein?
Antwort1
Die meisten Menschen streiten sich getline
überKodierungsstilBoden.
Es ist für die normale Verarbeitung fremd, awk
wenn der Code jeweils nur einen Datensatz verarbeitet.
getline
getline var < "file"
(wenn nicht als oder verwendet "cmd" | getline
) zieht den nächsten Datensatz (möglicherweise aus der nächsten Datei) in die Mitte der Codeanweisung. Man kann leicht den Überblick darüber verlieren, dass NR, FNR erhöht werden und sich FILENAME ändern kann.
Eine weitere Sache, die Sie bei der Verwendung nicht vergessen dürfen, ist, den Rückgabewert zu überprüfen, da dieser bei EOF 0 und im Fehlerfall <0 zurückgibt.
Es ist also nicht getline
oder if/while (getline) ...
, sondern:
if/while ((getline) > 0) { .... }
Oder:
if/while ((getline < "file") > 0) {...}
Die meisten Verwendungen getline
können durch die Verwendung eines zustandsmaschinenähnlichen Ansatzes umgekehrt werden.
Anstatt:
/pattern/ {getline; print}
Was wahrscheinlich falsch ist und geschrieben werden sollte:
/pattern/ && (getline) > 0 {print}
Du würdest:
found_pattern {print; found_pattern=0}
/pattern/{found_pattern=1}
Beachten Sie auch, wie sich die beiden unterscheiden, wennMusterwird in zwei aufeinanderfolgenden Zeilen abgeglichen.
Solange Sie sich dessen bewusst sind, getline
ist alles in Ordnung. Wenn Sie mehrere Dateien gleichzeitig verarbeiten möchten, benötigen Sie getline
, aber denken Sie daran, den Rückgabewert zu überprüfen:
while ((getline a < "a") > 0 && (getline b < "b") > 0) {
....