2013-05-13 34 views
79

Tôi đang học awk và tôi muốn biết nếu có tùy chọn ghi thay đổi vào tệp, tương tự như sed nơi tôi sẽ sử dụng tùy chọn -i để lưu sửa đổi đối với tệp.awk lưu sửa đổi tại chỗ

Tôi hiểu rằng tôi có thể sử dụng chuyển hướng để viết thay đổi. Tuy nhiên, có tùy chọn trong số awk để làm điều đó không?

+0

Cũng xem http://serverfault.com/a/547331/313521 để có câu trả lời chung chung hơn để "chỉnh sửa tệp tại chỗ với chuyển hướng". – Wildcard

Trả lời

68

Trong mới nhất GNU AWK (kể từ 4.1.0 released), nó có quyền lựa chọn "inplace" file editing:

[...] Tiện ích "inplace", được xây dựng bằng cách sử dụng cơ sở mới, có thể được sử dụng để mô phỏng các GNU "sed -i" tính năng. [...]

sử dụng Ví dụ:

$ gawk -i inplace '{ gsub(/foo/, "bar") }; { print }' file1 file2 file3 

Để giữ sao lưu:

$ gawk -i inplace -v INPLACE_SUFFIX=.bak '{ gsub(/foo/, "bar") } 
> { print }' file1 file2 file3 
+1

@sudo_O - Cảm ơn bạn đã trình diễn "tại chỗ". Đã bình chọn câu trả lời của bạn! – lind

+0

Có vẻ như tùy chọn có thể đã bị xóa? Với 4.1.3, tôi có "-i includefile \t \t --include = includefile" –

+0

@Khi tôi có cùng một câu hỏi. Tôi chỉ thử nó và nó hoạt động trên 4.1.3 của tôi. 'inplace' thực sự là một thư viện kèm theo' gawk' theo [câu trả lời của iiSeymour] (http://stackoverflow.com/a/16529730/2877364), vì vậy 'inplace' là một thứ có thể được bao gồm như một' includefile'. – cxw

84

Trừ khi bạn có GNU awk 4.1.0 hoặc mới hơn ...

Bạn sẽ không phải như một tùy chọn như sed của -i tùy chọn nên thay vì làm:

$ awk '{print $0}' file > tmp && mv tmp file 

Lưu ý: -i không phải là ma thuật, nó cũng tạo ra một tập tin tạm thời sed chỉ xử lý nó cho bạn.


Tính đến GNU awk 4.1.0 ...

GNU awk thêm chức năng này trong phiên bản 4.1.0 (phát hành 2013/10/05). Nó không thẳng tiến như chỉ đưa ra tùy chọn -i như được mô tả trong ghi chú đã phát hành:

Tùy chọn -i mới (từ xgawk) được sử dụng để tải tệp thư viện awk. Điều này khác với -f trong đó đối số phi tùy chọn đầu tiên được coi là một tập lệnh.

Bạn cần phải sử dụng kèm inplace.awk bao gồm tập tin để gọi phần mở rộng đúng như vậy:

$ cat file 
123 abc 
456 def 
789 hij 

$ gawk -i inplace '{print $1}' file 

$ cat file 
123 
456 
789 

Biến INPLACE_SUFFIX có thể được dùng để xác định phần mở rộng cho một tập tin sao lưu:

$ gawk -i inplace -v INPLACE_SUFFIX=.bak '{print $1}' file 

$ cat file 
123 
456 
789 

$ cat file.bak 
123 abc 
456 def 
789 hij 

Tôi hài lòng tính năng này đã được thêm vào nhưng với tôi việc triển khai không phải là rất awkish như sức mạnh là với sự conciseness của ngôn ngữ và -i inplace là 8 c bừa bãi dài I.M.O.

Đây là liên kết đến manual cho từ chính thức.

11

@sudo_O có quyền answer.

này không thể làm việc:

someprocess <file> file 

Vỏ thực hiện việc chuyển hướng trước kiểm soát bàn giao để someprocess (redirections). Chuyển hướng > sẽ cắt bớt tệp thành kích thước bằng không (redirecting output). Do đó, do thời gian một ngày nào đó được khởi chạy và muốn đọc từ tệp, không có dữ liệu để đọc.

2

Trong trường hợp bạn muốn một giải pháp awk-only mà không cần tạo một tập tin tạm thời và có thể sử dụng với version! = (gawk 4.1.0):

awk '{a[b++]=$0} END {for(c=0;c<=b;c++)print a[c]>ARGV[1]}' file 
+0

Nhưng bộ đệm này có lưu toàn bộ tệp vào bộ nhớ không? Hãy xem xét một tập tin 20GB. –

5

chỉ cần một chút hack hoạt động

echo "$(awk '{awk code}' file)" > file 
+5

Sẽ không hoạt động: dòng mới. – Lloeki

+1

@Lloeki cảm ơn, tôi đã sửa câu trả lời :) –

3

sau đây sẽ không hoạt động

echo $(awk '{awk code}' file) > file 

này nên làm việc

echo "$(awk '{awk code}' file)" > file 
3

Một cách khác là sử dụng sponge:

awk '{print $0}' your_file | sponge your_file 

đâu bạn thay thế '{print $0}' bởi bạn r awk script và your_file bằng tên của tệp bạn muốn chỉnh sửa tại chỗ.

sponge hấp thụ hoàn toàn đầu vào trước khi lưu vào tệp.

0

Sử dụng tee

awk '{awk code}' file | tee file 

lệnh tee diễn ra và thực hiện sau khi lệnh awk xong do |.

Các vấn đề liên quan