2013-12-17 17 views
36

Tôi đang cố gắng chạy lệnh shell từ bên trong awk cho mỗi dòng của một tập tin, và lệnh shell cần một đối số đầu vào. Tôi đã cố gắng sử dụng system(), nhưng nó không nhận ra đối số đầu vào.Làm cách nào để chuyển các biến từ awk sang lệnh shell?

Mỗi dòng của tệp này là địa chỉ của tệp và tôi muốn chạy một lệnh để xử lý tệp đó. Vì vậy, cho một ví dụ đơn giản, tôi muốn sử dụng lệnh 'wc' cho mỗi dòng và vượt qua $1 đến wc.

awk '{system("wc $1")}' myfile 
+0

Tìm kiếm trong SO trước tiên, đã có hàng trăm giải pháp. – BMW

+2

Tại sao bạn nghĩ awk là công cụ thích hợp cho công việc này? Nó có vẻ như 'xargs' hoặc một shell đơn giản' trong khi read line' loop sẽ tốt hơn và dễ dàng hơn. –

+1

Mặt khác: Tại sao bạn nghĩ wc là công cụ thích hợp cho công việc này? Có vẻ như các biến và hàm dựng sẵn awk sẽ tốt hơn và dễ dàng hơn? –

Trả lời

49

bạn đóng. bạn phải nối dòng lệnh với các biến awk:

awk '{system("wc "$1)}' myfile 
+0

cảm ơn, hoạt động! nhưng một câu hỏi nữa? Chúng ta có thể gán đầu ra cho một biến mới không? –

+0

có, chúng tôi có thể. '{newVar = system (...)}' @VahidMir – Kent

+5

Đó là cú pháp sai cho công việc này, đó là một ứng dụng sai cho hệ thống(), bản in không làm những gì bạn nghĩ nó sẽ làm, và không bạn không thể gán đầu ra của một hệ thống() gọi đến một biến awk, những gì bạn đăng trong bình luận của bạn gán mã trả về từ system() cho một biến. Thời gian cho một số cà phê @Kent! –

34

Bạn không thể lấy đầu ra của một awk system() cuộc gọi, bạn chỉ có thể nhận được trạng thái thoát. Sử dụng các getline/pipe hoặc getline/variable/pipe cấu trúc

awk '{ 
    cmd = "your_command " $1 
    while (cmd | getline line) { 
     do_something_with(line) 
    } 
    close(cmd) 
}' file 
+3

+1 cho cách chính xác để lấy đầu ra của lệnh shell, nhưng nói chung cú pháp để tạo biến là 'cmd =" ​​your_command \ "" $ 1 "" \ "' để đối số được trích dẫn khi cmd được thi hành và bạn cần kiểm tra kết quả của getline lớn hơn 0 hoặc bạn sẽ bị kẹt trong một vòng lặp vô hạn nếu nó không thành công. –

+1

+1. OP, nếu bạn cần lưu trữ đầu ra trong một var, chấp nhận câu trả lời này quá. của tôi không chính xác cho phép gán var. – Kent

2

FYI đây là làm thế nào để sử dụng awk để xử lý các file có tên được lưu trữ trong một tập tin (cung cấp chức năng wc giống như trong ví dụ này):

gawk ' 
NR==FNR { ARGV[ARGC++]=$0; next } 
{ nW+=NF; nC+=(length($0) + 1) } 
ENDFILE { print FILENAME, FNR, nW, nC; nW=nC=0 } 
' file 

Việc sử dụng trên GNU lúng túng cho ENDFILE. Với các awks khác chỉ lưu trữ các giá trị trong một mảng và in trong một vòng lặp trong phần END.

0

Hoặc sử dụng các đường ống | như trong bash sau đó truy xuất các đầu ra trong một biến với awk của getline, như thế này

zcat /var/log/fail2ban.log* | gawk '/.*Ban.*/ {print $7};' | sort | uniq -c | sort | gawk '{ "geoiplookup " $2 "| cut -f2 -d: " | getline geoip; print $2 "\t\t" $1 " " geoip}' 

dòng đó sẽ in tất cả các IP bị cấm từ máy chủ của bạn cùng với nguồn gốc của chúng (quốc gia) sử dụng gói geoip-bin.

Phần cuối cùng của một lót là một trong đó ảnh hưởng đến chúng tôi:

gawk '{ "geoiplookup " $2 "| cut -f2 -d: " | getline geoip; print $2 "\t\t" $1 " " geoip}' 

Nó chỉ đơn giản nói: chạy lệnh "geoiplookup 182.193.192.4 | -f2 -d:" ($ 2 được thay thế như bạn có thể đoán) và đưa kết quả của lệnh đó trong geoip (bit | getline geoip). Tiếp theo, in thứ gì đó và bất cứ thứ gì bên trong biến số geoip.

Ví dụ hoàn chỉnh và kết quả có thể được tìm thấy here, một bài viết tôi đã viết.

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