Phân phối tập lệnh: Tôi nên sử dụng / bin / gawk hoặc / usr / bin / gawk cho shebang?


12

Là gawk trong / bin hoặc / usr / bin thường? Tôi sẽ đi với #!/usr/bin/env gawknhưng sau đó tôi không thể sử dụng đối số. Ngay bây giờ tôi đang sử dụng #!/bin/gawk -f. Kịch bản rất dài và chứa rất nhiều trích dẫn đơn và hoạt động với stdin.

Hướng dẫn sử dụng GNU Awk có phần 1.1.4 Các chương trình awk có thể thực thi trong đó nó sử dụng #! / Bin / awk trong ví dụ của nó nhưng tiếp tục nói:

Lưu ý rằng trên nhiều hệ thống awkcó thể được tìm thấy /usr/binthay vì trong /bin. Emptor caveat.

Hầu hết mọi người làm gì? Tôi đã đọc sed được cho là đã được chuẩn hóa trong / bin trong khi perl được cho là đã được chuẩn hóa trong / usr / bin (cùng trang với liên kết sed nhưng họ sẽ không cho phép tôi tạo liên kết thứ ba cho bài đăng này). Thế còn awk / gawk? Có ai biết cái nào phổ biến hơn hay phổ biến hơn không?


Tại sao bạn sử dụng -f? Không /bin/gawkđủ sao? Ngoài ra, điều này có thể có liên quan.
terdon

Câu trả lời:


7

Shebang không có nghĩa là linh hoạt . Có thể có một số trường hợp có tham số thứ hai hoạt động , tôi nghĩ FreeBSD là một trong số đó.

gawk và hầu hết các tiện ích đi kèm với hệ điều hành dự kiến ​​sẽ có /usr/bin/.

Trong những ngày UNIX cũ, người ta thường /usr/gắn trên NFS hoặc một số phương tiện ít tốn kém hơn để tiết kiệm không gian đĩa cục bộ và chi phí cho mỗi máy trạm. /bin/được cho là có mọi thứ cần thiết để khởi động ở chế độ người dùng . Vì /usr/không được gắn trên một phương tiện đáng tin cậy, /bin/bao gồm đủ các tiện ích để làm cho nó đủ thân thiện để quản lý và khắc phục sự cố chung.

Điều này đã được kế thừa trong Linux ban đầu, nhưng vì không gian đĩa không còn là vấn đề nữa và trong hầu hết các trường hợp /usr/là trong hệ thống tập tin gốc, xu hướng hiện nay là chuyển mọi thứ vào /usr/bin(ít nhất là trong thế giới Linux). Vì vậy, hầu hết các tiện ích được cài đặt bởi một bản phân phối dự kiến ​​sẽ được tìm thấy ở đó. Ngay cả những tiện ích cơ bản nhất, như cp, rm, lsvv (tốt, chưa).

Về sự lựa chọn shebang. Theo truyền thống, đây là điều mà quản trị viên hoặc người dùng phải chỉnh sửa theo môi trường của họ. Đối với tất cả một nhà phát triển biết, trong các hệ thống của người khác, người phiên dịch có thể là bất cứ nơi nào trong hệ thống tập tin (ví dụ /usr/local/bin, /opt/gawk-4.0.1/bin). Các tập lệnh được đóng gói đúng cách (vòng / phút, deb, v.v.) đi kèm với sự phụ thuộc vào gói phân phối (ví dụ: trình thông dịch có một vị trí đã biết) hoặc tập lệnh cấu hình để thiết lập hashbang thích hợp trong khi cài đặt.


14

Nếu bạn không cần truyền đối số cho lệnh thì đó #!/usr/bin/env gawklà cách để thực hiện, tuy nhiên nhiều hạt nhân (bao gồm cả Linux) chỉ chấp nhận một đối số duy nhất cho các chương trình shebang.

Mặt khác, bạn có thể tạo một chương trình polyglot vừa là trình bao bọc vỏ và tập lệnh awk. Đây là một cho awk.

#!/bin/sh
true + /; exec gawk -f "$0"; exit; / {}
# awk script starts here

Phân tích cú pháp shell:

  • true + /;- lệnh true(không làm gì) với hai đối số trơ +/.
  • Cuộc gọi đến gawk. Đây có thể là bất kỳ đoạn mã shell nào không chứa dòng mới và nơi viết dấu gạch chéo \/(shell không có ý gì ngoại trừ dấu ngoặc kép bên trong).
    Cuộc gọi sử dụng execđể thay thế shell bằng gawk thay vì thực hiện gawk như một quy trình con.
  • exit;- thoát khỏi vỏ, trong trường hợp không tìm thấy gawk. Bất cứ điều gì sau đó được bỏ qua, ngoại trừ rằng nó phải là cú pháp shell hợp lệ trong trường hợp shell cố phân tích toàn bộ dòng trước khi bắt đầu thực thi nó.

Phân tích cú pháp Awk:

  • Các bit giữa các dấu gạch chéo là một biểu thức thông thường.
  • true + /REGEX/- một điều kiện. truelà một biến không xác định nên giá trị số của nó là 0, không quan trọng.
  • {} - Nếu nói điều kiện giữ, không làm gì cả.

5

Giải pháp đề xuất của Gilles thực sự là một cách tiếp cận rất tốt (cuối cùng cũng có danh tiếng để bỏ phiếu trong bài đăng của mình :)).

Trong mọi trường hợp, theo như tôi hiểu execlệnh, nó làm cho exitquyền sau khi nó không cần thiết, thực sự không thể truy cập được, vì quá trình shell được thay thế bằng awk.

Ngoài ra, để cho phép awktập lệnh truy cập các tham số gọi của nó, tôi sẽ đề xuất một số thay đổi trong giải pháp được đề xuất:

#!/bin/sh
true + /; exec -a "$0" gawk -f "$0" -- "$@"; / {}
# awk script starts here

Tập -a "$0"lệnh cho phép tập lệnh có quyền truy cập vào tên gọi của nó, nếu không, tập lệnh sẽ luôn nhận được một awkhoặc gawkkhi truy cập vào ARGV[0]biến. Tương tự, "$@"tập lệnh cho phép tập lệnh truy cập các tham số còn lại trong ARGV[1...N]mảng và tập lệnh --trước cho phép tập lệnh nhận các -<something>đối số mà không cần gawk diễn giải chúng là dành cho nó.

Một điều cần nhớ / xem xét là thêm một exit(0);câu lệnh vào cuối BEGIN { ... }khối awkchương trình tập lệnh, nếu không awksẽ đe dọa tất cả các tham số được truyền cho tập lệnh dưới dạng tệp đầu vào. (Xin lưu ý rằng nó không có gì để làm cả, với exitcâu lệnh chúng tôi đã xóa khỏi true + ...dòng, đây là một câu lệnh shell không thể truy cập trong khi lối thoát được đề xuất này nằm trong mã awk).


Các exit(0)rất hữu ích! Ngoài ra, đối với người dùng macos, hãy xem ý chính này: Một
Seamus
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.