Chuyển hướng đầu ra của bản in sang nhiều tập tin trong awk


8

Tôi muốn in cùng một dòng đến 2 tập tin khác nhau. Những gì tôi đang làm bây giờ là:

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

Tôi có thể viết một lệnh duy nhất để chuyển hướng nó đến hai tệp khác nhau không?

BIÊN TẬP

Tôi không muốn in toàn bộ đầu ra lệnh của mình ra nhiều tệp, tôi muốn viết một số bản ghi dựa trên một số điều kiện vào nhiều tệp, tôi đang in nó trong awktập lệnh vì vậy tôi cần một cách hiệu quả để thực hiện.


Nó không rõ ràng những gì bạn muốn. Bạn nói rằng chúng là cùng một dòng , nhưng sau đó bạn nói rằng chúng không phải là toàn bộ dòng .
LatinSuD

Có phải là bạn muốn sử dụng một biến? MYLINE=ID[i]" "...; print MYLINE >> file1.txt; print MYLINE >> file2.txt?
LatinSuD

Câu trả lời:


11

Bạn không thể làm điều đó với awk.

Sử dụng tee, bạn có thể làm một cái gì đó như thế này:

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

Sử dụng tee -anếu bạn muốn chắp thêm thay vì ghi đè các tệp đã tồn tại.

Nếu bạn không muốn in toàn bộ đầu ra, bạn có thể thử:

awk '
    BEGIN {outfile["a.txt"];outfile["b.txt"]}
    { for (file in outfile) { print > file } }' file

Cảm ơn bạn đã trả lời nhưng tôi không muốn in toàn bộ đầu ra lệnh của mình ra nhiều tệp.
Aashu

2
Bạn có thể làm đường ống bên trong awk. command = "tee file1.txt file2.txt"; print message | command;
Matt

@mtm: Vâng, tôi muốn thêm nó nhưng Stéphane Chazelas đã có câu trả lời.
cuonglm

10

Trong awk, thay vì chuyển hướng đến một tệp với print "text" > "file", bạn có thể chuyển hướng đến một lệnh bằng cách sử dụng:

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

Lần đầu tiên bạn sử dụng lệnh đó |, sẽ awksinh ra lệnh và lần tiếp theo nó sử dụng lại cùng một lệnh, vì vậy nó không bắt đầu mới teemỗi lần bạn làm điều đó và không ghi đè lên các tệp (bạn cần gọi close("tee file1.txt file2.txt")nếu bạn muốn awkđể bắt đầu một lệnh mới trong lần tiếp theo). Tuy nhiên, nếu bạn làm cả hai > "file1.txt"| "tee file1.txt..."sẽ có xung đột.

Sau đó bạn có thể muốn sử dụng >> "file1.txt"| "tee -a file1.txt..."thay vào đó.

Tuy nhiên, tôi vẫn đi theo cách tiếp cận của @ cuonglmfor hoặc sử dụng một awkchức năng vì nó sẽ sạch hơn và hiệu quả hơn.


Tại sao bạn trích dẫn lệnh tee? Có bất kỳ lý do đằng sau đó?
polym

5
@polym: Anh ấy đã sử dụng pipe bên trong awkscript, không phải trong shell như câu trả lời của tôi. Xem: gnu.org/software/gawk/manual/html_node/Redirection.html
cuonglm

@Stephane +1 cho lời giải thích hay, cảm ơn.
Aashu

4

Hàm do người dùng xác định có thể làm cho mã của bạn sạch hơn và gây ra sự trùng lặp ít hơn, nếu đó là vấn đề đáng lo ngại.

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" );'

Hoặc mã cứng các tập tin nếu đó là tất cả những gì bạn cần.

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 );'

3

Bạn có thể làm điều này với sed- nhưng không có ý tưởng rõ ràng hơn về đầu vào của bạn, tôi không biết làm thế nào để chứng minh cụ thể. Tuy nhiên, đây là một ví dụ chung:

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

Điều đó chỉ ghi các dòng chứa a 1đến onesfile.txtvà nếu không 3- mọi thứ khác sẽ bị xóa. Đây là một ví dụ rất cơ bản về cách thức này có thể hoạt động, nhưng nếu bạn có thể cung cấp đầu vào mẫu, tôi có thể làm tốt hơn một chút.

Sau khi sedmở tệp để ghi, nó vẫn mở cho đến khi quá trình hoàn tất - nó không liên tục cắt bớt ghi của chính nó - các mô tả tệp được giữ lại cho vòng đời của quy trình.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.