Có 2 cách để đặt vars awk thông qua dòng lệnh?


10

Tôi nhận thấy một awkví dụ O'Reilly (1997) đã gán biến awk bằng cách đặt nó trên dòng lệnh sau văn bản chương trình. Nó hoạt động, nhưng tôi không thể tìm thấy cú pháp này trong man / thông tin awk . Có phải tôi vừa bỏ lỡ nó; nó có bị lỗi không ...? Cú pháp duy nhất tôi thấy trong hướng dẫn là -vtùy chọn.

awk '/home/{print foo, bar}' foo="cat" bar="dog" /proc/$$/cmdline

Đầu ra: cat dog

Câu trả lời:


11

Nó thực sự có trong POSIX awk(liên kết đến POSIX 2008, tôi cũng tin rằng các phiên bản trước đó). -vđược mô tả trong phần Tùy chọn , cách khác là trong phần Toán hạng .

Có một sự khác biệt giữa -vvà chuyển các bài tập ở cuối với tên tệp:

  • Với -v:

Ứng dụng phải đảm bảo rằng đối số gán có cùng dạng với toán hạng gán. Việc gán biến được chỉ định sẽ xảy ra trước khi thực hiện chương trình awk, bao gồm các hành động được liên kết với các mẫu BEGIN (nếu có). Nhiều lần xuất hiện của tùy chọn này có thể được chỉ định.

  • Trộn lẫn với tên tệp:

[...] Mỗi lần gán biến như vậy sẽ xảy ra ngay trước khi xử lý tệp sau , nếu có. Do đó, một phép gán trước đối số tệp đầu tiên sẽ được thực thi sau các hành động BEGIN (nếu có), trong khi việc gán sau đối số tệp cuối cùng sẽ xảy ra trước các hành động END (nếu có). Nếu không có đối số tệp, các phép gán sẽ được thực thi trước khi xử lý đầu vào tiêu chuẩn.

Thí dụ:

$ cat input 
hello
hello
$ awk -v var=one 'BEGIN{print var} /hello/{print var} END{print var}' \
    var=two input var=three input var=four
one
two
two
three
three
four

Ồ Điều đó thêm một số điểm kiểm soát thú vị ... nó chắc chắn sẽ có ích. Cảm ơn ...
Peter.O

1
"Wow!" Ban đầu của tôi vẫn giữ vững, nhưng nó đã được giảm bớt phần nào bằng cách nhìn sâu hơn vào câu trả lời của Arcege ... Tôi đã thử nó với một tập tin thực sự có tên "var = ba" ... được awkưu tiên là một nhiệm vụ thay đổi ... Điều này có một hệ quả tất yếu , I E. Trong mọi trường hợp khi tên tệp có dạng này, nó sẽ bị bỏ qua và biến sẽ được đặt ... Dường như cách duy nhất để tránh xung đột này là đảm bảo rằng tên tệp cho thư mục làm việc hiện tại phải luôn được đặt trước với con đường tương đối của họ:./var=three
Peter.O

@ Peter.O, vâng, đó cũng là một trong những lý do -vcú pháp được giới thiệu. Bạn nên nghĩ về -vcú pháp như là cách ưa thích để làm bài tập, đi tiếp.
dubiousjim

@ Peter.O, điểm tuyệt vời về "gotcha" nếu tên tệp là một phép gán biến hợp lệ. Nếu bạn đang sử dụng biến shell chứa tên tệp và chuyển nó làm đối số cho awk, bạn có thể sử dụng lệnh bắt sau:[ "$myfile" == "${myfile#/}" ] && myfile="./$myfile"
Wildcard

4

Đây là một kiểu cũ của việc thiết lập các biến bên ngoài awk. Đó là mơ hồ (nếu bạn có một tên tệp được đặt tên foo=cat), vì vậy các phiên bản sau đó đã thêm một -vtùy chọn. Nó có thể hoạt động để tương thích ngược, nhưng bạn không thể đảm bảo. Và như tôi đã nói, -vtùy chọn này mới hơn, vì vậy không phải tất cả các phiên bản awkcó thể hỗ trợ nó.


Nhận xét của bạn về khả năng xảy ra xung đột tên tệp là tốt ... Tôi đã kiểm tra nó và nó chắc chắn là một vấn đề. Tôi đã viết thêm một chút về nó trong một bình luận cho câu trả lời của Mat .. Thansk vì đã nhấn mạnh vấn đề này (+1)
Peter.O

2
Trên thực tế, như được giải thích trong [Mat s answer](http://unix.stackexchange.com/a/34258/9537), -v` và gán đối số là khác nhau khi chúng có hiệu lực. Cũng -vlà trong POSIX và nên có mặt trong tất cả các awktriển khai cổ xưa nhất . Sử dụng ./hoặc đảm bảo tên tệp chứa ký tự không định danh có lẽ là cách đáng tin cậy nhất để phân tán.
jw013
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.