Wenn ich Eingaben habe, ist es dann besser, die Daten zu filtern, bevor ich meine awk
Aktion ausführe, oder sollte ich die gesamte Filterung durchführen awk
?
Nehmen wir beispielsweise die folgende Eingabe an:
$ echo "foo\nbar\nbaz"
foo
bar
baz
Soll ich ausführen:
$ echo "foo\nbar\nbaz" | sed 1q | awk '{ print $0 " cats" }'
foo cats
Oder:
$ echo "foo\nbar\nbaz" | awk 'NR == 1 { print $0 " cats" }'
foo cats
- Warum sollte ich eines von beiden ausführen?
- Sollte ich ein anderes Werkzeug verwenden?
- Welche Faktoren sollte ich berücksichtigen?
- Wie kann ich diese Faktoren testen?
Antwort1
In diesem konkreten Fall ist die zweite Option die bessere.
Im Allgemeinen ist es effizienter, die Anzahl der Dienstprogramme in einer Pipeline zu minimieren. Es ist am besten, unnötige Prozesse nicht zu forken (starten) (wie in Ihrem ersten Beispiel mit einem unnötigen sed
Prozess). Im Internet findet man leicht Beispiele für Beschwerden übernutzlose Verwendungen von Katzen.
Bei den meisten modernen Unix-ähnlichen Systemen * wird das Forking recht effizient durchgeführt, es hängt jedoch von der Größe des zu startenden Prozesses ab; beispielsweise wäre das Starten von perl
oder viel langsamer als das Starten von oder .python
sed
awk
Bei einmaligen Befehlen spielt dies keine so große Rolle. Wenn sich Ihre Pipeline jedoch in einer Schleife befindet und viele Male ausgeführt wird, kann das Entfernen unnötiger Prozesse aus Ihrer Pipeline die Gesamtausführungszeit erheblich verkürzen.
Spezifische Fragen
Warum sollte ich eines von beiden ausführen?
Wenn Sie mit der Syntax des einen besser vertraut sind als mit der des anderen, ist es für die Lesbarkeit (und Wartbarkeit) des Codes möglicherweise besser, das Tool/die Sprache zu verwenden, mit der Sie am besten vertraut sind.
Sollte ich ein anderes Werkzeug verwenden?
In diesem konkreten Fall würde ich das nicht glauben. Sowohl als awk
auch sed
sind geeignete Werkzeuge für diese Art von Arbeit.
Welche Faktoren sollte ich berücksichtigen?
Wenn Sie mehrere Dateien verarbeiten müssen (z. B. in einer Schleife), ist Geschwindigkeit/Effizienz wichtig.
Wenn Sie nur ab und zu eine große Datei verarbeiten, ist die Lesbarkeit des Codes möglicherweise wichtiger.
Wie kann ich diese Faktoren testen?
Sie können verschiedene Versionen mit dem time
Dienstprogramm profilieren, das als in Bash integrierte Shell verfügbar ist – aber auch als eigenständiges ausführbares Programm. Das Ausführen der beiden Beispielbefehle zeigt beispielsweise, dass das erste Beispiel 0,012 Sekunden länger dauerte als das zweite.
$ time echo "foo\nbar\nbaz" | sed 1q | awk '{ print $0 " cats" }'
foo\nbar\nbaz cats
real 0m0.056s
user 0m0.000s
sys 0m0.045s
$ time echo "foo\nbar\nbaz" | awk 'NR == 1 { print $0 " cats" }'
foo\nbar\nbaz cats
real 0m0.044s
user 0m0.000s
sys 0m0.031s
Beachten Sie, dass Profilierungs-Benchmarks von der Systemlast und anderen einschränkenden Faktoren beeinflusst werden. Sie müssen dies also viele Male wiederholen, um ein echtes Bild davon zu erhalten, welche Version schneller als die andere ist.
* Mit MS Windows, ForkingIstteurer, daher macht es einen Unterschied, wenn man in Umgebungen wie Cygwin die Anzahl der gestarteten Prozesse minimiert.
Antwort2
Es reicht aus,awk(odersed) Werkzeug für solche einfachen Fälle. Eine Kombination mehrerer Werkzeuge wäre zu kompliziert und oft redundant:
echo -e "foo\nbar\nbaz" | awk 'NR==1{print $0" cats"}'
Die Ausgabe:
foo cats
Welche Faktoren sollte ich berücksichtigen?
Stellen Sie sicher, dass die erforderliche Textverarbeitung die Kombination mehrerer verschiedener Tools erfordert. Andernfalls nutzen Sie die Leistung eines einzelnen Tools.
Nehmen wir an, ich muss nur ein bestimmtes Wort vor dem ersten Wort in der Eingabezeichenfolge hinzufügen - das geht auch ganz einfach mitsedWerkzeug:
echo -e "foo\nbar\nbaz" | sed 's/^.*$/& cats/; 1q'
foo cats
echo -e
, e
Flag „ermöglicht die Interpretation von Backslash-Escapezeichen“
Wie dem auch sei, es hängt davon ab, wie komplex Ihr Eingabetext ist und wie ausgefeilt Ihre Textverarbeitungsregeln sind.