Umleiten der Druckausgabe in mehrere Dateien in awk

8

Ich möchte die gleichen Zeilen in 2 verschiedene Dateien drucken. Was ich gerade mache ist:

print ID[i]" "Value[i]" "TS1[i]" "TS2[i] > "file1.txt";
print ID[i]" "Value[i]" "TS1[i]" "TS2[i] > "file2.txt";

Kann ich einen einzelnen Befehl schreiben, um ihn in zwei verschiedene Dateien umzuleiten?

BEARBEITEN

Ich möchte nicht meine gesamte Befehlsausgabe in mehrere Dateien drucken, sondern einige Datensätze basierend auf bestimmten Bedingungen in mehrere Dateien schreiben. Ich drucke dies innerhalb eines awkSkripts, daher benötige ich eine effiziente Methode, um dies zu tun.

Aashu
quelle
Es ist nicht klar, was Sie wollen. Sie sagen, dass es sich um dieselben Zeilen handelt , aber dann sagen Sie, dass es sich nicht um ganze Zeilen handelt .
LatinSuD
Möchten Sie eine Variable verwenden? MYLINE=ID[i]" "...; print MYLINE >> file1.txt; print MYLINE >> file2.txt?
LatinSuD

Antworten:

11

Sie können es nicht mit tun awk.

Mit teekönnen Sie so etwas tun:

$ awk '{print ID[i]" "Value[i]" "TS1[i]" "TS2[i]}' file | tee out1 out2

Verwenden tee -aSie diese Option, wenn Sie vorhandene Dateien anhängen möchten, anstatt sie zu überschreiben.

Wenn Sie nicht die gesamte Ausgabe drucken möchten, können Sie Folgendes versuchen:

awk '
    BEGIN {outfile["a.txt"];outfile["b.txt"]}
    { for (file in outfile) { print > file } }' file
cuonglm
quelle
Vielen Dank für Ihre Antwort, aber ich möchte nicht meine gesamte Befehlsausgabe in mehrere Dateien drucken.
Aashu
2
Sie können das Rohr in awk machen. command = "tee file1.txt file2.txt"; print message | command;
Matt
@mtm: Ja, ich möchte es hinzufügen, aber Stéphane Chazelas hatte geantwortet.
Cuonglm
10

awkAnstatt zu einer Datei mit print "text" > "file"umzuleiten, können Sie innerhalb zu einem Befehl umleiten, indem Sie:

print "something" | "tee file1.txt file2.txt"

Wenn Sie das zum ersten Mal verwenden, |wird awkder Befehl erzeugt und beim nächsten Mal wird derselbe Befehl erneut verwendet, sodass nicht teejedes Mal ein neuer Befehl gestartet wird und die Dateien nicht überschrieben werden (Sie müssen aufrufen, close("tee file1.txt file2.txt")wenn Sie möchten awkum beim nächsten Mal einen neuen Befehl zu starten). Wenn Sie beide jedoch tun > "file1.txt"und | "tee file1.txt..."es wird ein Konflikt.

Möglicherweise möchten Sie dann >> "file1.txt"und | "tee -a file1.txt..."stattdessen verwenden.

Ich würde jedoch immer noch den forAnsatz von @ cuonglm wählen oder eine awkFunktion verwenden, da diese sauberer und effizienter wäre.

Stéphane Chazelas
quelle
Warum haben Sie den Abschlagbefehl zitiert? Gibt es einen Grund dafür?
Polym
5
@polym: Er hat Pipe in awkScript verwendet, nicht in Shell wie meine Antwort. Siehe: gnu.org/software/gawk/manual/html_node/Redirection.html
cuonglm
@Stephane +1 für nette Erklärung, danke.
Aashu
4

Eine benutzerdefinierte Funktion kann Ihren Code sauberer machen und weniger Doppelarbeit verursachen, wenn dies der Fall ist.

function print_to_files( message, file_a, file_b ) {
   print message > file_a;
   print message > file_b;
}

message = sprintf( "%s %s %s %s", ID[i], Value[i], TS1[i], TS2[i] )
print_to_files( message , "filea", "fileb" );'

Oder codieren Sie die Dateien hart, wenn das alles ist, was Sie brauchen.

function print_to_files( message ) {
   print message > "/path/to/filea";
   print message > "/path/to/fileb";
}

message = sprintf( "%s %s %s %s", ID[i], Value[i], TS1[i], TS2[i] )
print_to_files( message );'
Matt
quelle
3

Sie können dies mit tun sed- aber ohne eine klarere Vorstellung von Ihrer Eingabe weiß ich nicht, wie ich sie konkret demonstrieren soll. Dennoch ist hier ein allgemeines Beispiel:

seq 10 | sed -ne '/1/w ./onesfile.txt' -e '/3/w threesfile.txt'

Das schreibt nur die Zeilen mit a 1an onesfile.txtund sonst für 3- alles andere wird gelöscht. Dies ist ein sehr einfaches Beispiel dafür, wie dies funktionieren könnte, aber wenn Sie Beispiel-Input liefern könnten, könnte ich es etwas besser machen.

Sobald sedeine Datei zum Schreiben geöffnet wird, bleibt sie geöffnet, bis der Prozess abgeschlossen ist. Die eigenen Schreibvorgänge werden nicht kontinuierlich abgeschnitten. Die Dateideskriptoren bleiben während der gesamten Laufzeit des Prozesses erhalten.

mikeserv
quelle