2 Stimmen

Kann ich mehrere Befehle aneinanderreihen und dafür sorgen, dass sie alle dieselbe Eingabe von stdin erhalten?

Gibt es in der Bash eine Möglichkeit, mehrere Befehle zu verketten, die alle die gleiche Eingabe von stdin erhalten? Das heißt, ein Befehl liest stdin, führt eine Verarbeitung durch und schreibt die Ausgabe in eine Datei. Der nächste Befehl in der Kette erhält dieselbe Eingabe, die der erste Befehl erhalten hat. Und so weiter.

Nehmen wir zum Beispiel eine große Textdatei, die durch Filterung des Inhalts in mehrere Dateien aufgeteilt werden soll. Etwa so:

cat food_expenses.txt | grep "coffee" > coffee.txt | grep "tea" > tea.txt | grep "honey cake" > cake.txt

Dies funktioniert offensichtlich nicht, denn der zweite grep erhält die Ergebnisse des ersten grep Ausgabe und nicht die ursprüngliche Textdatei. Ich habe versucht, einzufügen T-Stücke aber das hilft nicht. Gibt es irgendeine Bash-Magie, die den ersten grep dazu bringt, seine Eingabe in die Leitung, nicht in den Ausgang?

Übrigens war die Aufteilung einer Datei ein einfaches Beispiel. Stellen Sie sich vor, Sie würden einen kontinuierlichen Live-Textstrom, der über ein Netzwerk kommt, aufteilen (durch Mustersuche filtern) und die Ausgabe in verschiedene benannte Pipes oder Sockets schreiben. Ich würde gerne wissen, ob es eine einfache Möglichkeit gibt, dies mit einem Shell-Skript zu tun.

(Diese Frage ist eine bereinigte Version meiner früher auf der Grundlage von Antworten, die auf die Unklarheit hinwiesen)

1voto

Stan Graves Punkte 6305

Mir ist nicht klar, warum die Filterung in verschiedenen Schritten erfolgen muss. Ein einziges awk-Programm kann alle eingehenden Zeilen scannen und die entsprechenden Zeilen an einzelne Dateien weiterleiten. Dies ist ein sehr einfacher Versand, der mehrere sekundäre Befehle füttern kann (d.h. persistente Prozesse, die die Ausgabedateien auf neue Eingaben überwachen, oder die Dateien könnten Sockets sein, die im Voraus eingerichtet werden und in die der awk-Prozess schreibt).

Wenn es einen Grund gibt, warum jeder Filter jede Zeile sehen muss, dann entfernen Sie einfach die "next;"-Anweisungen, und jeder Filter sieht jede Zeile.

$ cat split.awk
BEGIN{}
/^coffee/ {
    print $0 >> "/tmp/coffee.txt" ;
    next;
}
/^tea/ {
    print $0 >> "/tmp/tea.txt" ;
    next;
}
{ # default
    print $0 >> "/tmp/other.txt" ;
}
END {}
$

0voto

nik Punkte 12812

Sie können wahrscheinlich ein einfaches AWK-Skript schreiben, um dies auf einen Schlag zu erledigen. Können Sie das Format Ihrer Datei ein wenig genauer beschreiben?

  • Sind sie durch Leerzeichen/Kommata getrennt?
  • Haben Sie die Artikelbeschreibungen in einer bestimmten "Spalte", wobei die Spalten durch ein Trennzeichen wie Leerzeichen, Komma oder etwas anderes definiert sind?

Wenn Sie sich mehrere grep-Durchläufe leisten können, wird dies funktionieren,

grep coffee food_expanses.txt> coffee.txt
grep tea food_expanses.txt> tea.txt

und so weiter.

0voto

Aftermathew Punkte 1928

Unter der Annahme, dass Ihre Eingabe nicht unendlich ist (wie im Fall eines Netzwerkstroms, den Sie nie schließen wollen), könnte ich eine Subshell verwenden, um die Daten in eine temporäre Datei zu speichern, und dann eine Reihe anderer Subshells, um sie zu lesen. Ich habe das nicht getestet, aber vielleicht würde es so aussehen { cat inputstream > tempfile }; { grep tea tempfile > tea.txt }; { grep coffee tempfile > coffee.txt };

Ich bin mir jedoch nicht sicher, ob es eine elegante Lösung dafür gibt, dass die Datei zu groß wird, wenn der Eingabestrom nicht in der Größe begrenzt ist.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X