Mục đích nào xây dựng đại tràng phục vụ?


45

Tôi đã hack rất nhiều kịch bản shell, và đôi khi những điều đơn giản nhất lại gây trở ngại cho tôi. Hôm nay tôi đã chạy qua một kịch bản sử dụng rộng rãi các :nội dung bash (dấu hai chấm).

Sự thông thạo dường như đủ đơn giản:

: (a colon)  
     : [arguments]  

Không làm gì ngoài việc mở rộng đối số và thực hiện chuyển hướng. Trạng thái trả về bằng không.

Tuy nhiên trước đây tôi chỉ thấy điều này được sử dụng trong các cuộc biểu tình mở rộng vỏ. Trường hợp sử dụng trong tập lệnh tôi chạy qua đã sử dụng rộng rãi cấu trúc này:

if [ -f ${file} ]; then
    grep some_string ${file} >> otherfile || :
    grep other_string ${file} >> otherfile || :
fi

Thực tế đã có hàng trăm greps, nhưng chúng chỉ giống nhau hơn. Không có chuyển hướng đầu vào / đầu ra nào ngoài cấu trúc đơn giản ở trên. Không có giá trị trả về được kiểm tra sau trong tập lệnh.

Tôi đang đọc điều này như một công trình vô dụng nói rằng "hoặc không làm gì cả". Mục đích nào có thể kết thúc những greps này với "hoặc không làm gì" phục vụ? Trong trường hợp nào, cấu trúc này sẽ gây ra một kết quả khác ngoài việc đơn giản là loại bỏ khỏi || :tất cả các trường hợp?


10
Một mục đích có thể tôi có thể thấy là sử dụng :thay thế true. Có lẽ errexitđược đặt và tác giả không quan tâm đến trạng thái thoát của một số lệnh.
jw013


trang được liên kết Stackoverflow là IMO toàn diện hơn một chút (rất tốt để đọc cả trang này và trang được liên kết).
Trevor Boyd Smith

Câu trả lời:


29

Có vẻ như :s trong tập lệnh của bạn đang được sử dụng thay cho true. Nếu grepkhông tìm thấy kết quả khớp trong tệp, nó sẽ trả về mã thoát không khác; như jw013 đề cập trong một bình luận, nếu errexitđược đặt, có thể là -etrên dòng shebang, tập lệnh sẽ thoát nếu bất kỳ lỗi nào grepkhông tìm thấy kết quả khớp. Rõ ràng, đó không phải là điều mà tác giả muốn, vì vậy, ông đã thêm vào || :để làm cho trạng thái thoát của lệnh ghép cụ thể đó luôn luôn bằng không, giống như phổ biến hơn (theo kinh nghiệm của tôi) || true/ || /bin/true.


Tât nhiên. Đây là khái niệm về tập lệnh xây dựng RPM và trong khi tôi không thấy bất kỳ mã thoát nào kiểm tra bên trong tập lệnh, tôi đã quên xem xét rằng quy trình cha có thể đang xem.
Caleb

8
Nếu đó là trường hợp, tôi sẽ gọi nó là thực hành kịch bản kém. Nó có chức năng tương đương với việc sử dụng truethay thế, nhưng mục đích ngữ nghĩa rõ ràng hơn nhiều true. :là phù hợp hơn khi muốn có một NOP rõ ràng.
jw013

Theo kinh nghiệm của tôi, đây là một thực tiễn phổ biến trong các kịch bản RPM. Có lẽ không nên, nhưng chúng ta ở đó.
mattdm

một số người theo chủ nghĩa thuần túy thích :thay truevì bởi vì :là một tích bashhợp trong đó truethường là một nhị phân được biên dịch với nhiều chi phí hơn. thông thường tôi sử dụng truevì mã dễ đọc hơn (tương tự tôi thích sử dụng sourcethay vì .).
Trevor Boyd Smith

36

Nội dung :cũng hữu ích với mở rộng hệ vỏ "gán giá trị mặc định" của Bash, trong đó việc mở rộng thường chỉ được sử dụng cho hiệu ứng phụ và giá trị được mở rộng bị loại bỏ:

# assign FOO=bar iff FOO is unset
: ${FOO:=bar}

2
Đến đây để tìm kiếm điều này, đã gặp khó khăn khi tôi thấy mẫu này trong một tập lệnh để khai báo các giá trị mặc định.
ffledgling

21

Tôi có thể nghĩ về hai nơi tôi đã sử dụng :trong quá khứ.

while :
do
     shell commands
     some exit condition
done

Đó là một vòng lặp mãi mãi.

function doSomethingStub {
    :
}

Đặt trong một chức năng còn sơ khai, chỉ để có được dòng điều khiển cấp cao nhất chính xác.

Một lần sử dụng mà tôi đã thấy trong Ngày xưa: Thay vì một dòng #!/bin/sh(hoặc bất cứ điều gì), bạn sẽ thấy một :dòng. Một số nhân Real Unix cũ hoặc shell Unix thực sẽ sử dụng điều đó có nghĩa là "Tôi là tập lệnh shell, đã điều hành tôi". Khi tôi nhớ lại thì đây chỉ là khi csh đang xâm nhập như một vỏ tương tác phổ biến.


@BruceEdiger: Bạn có tham khảo dòng "shecolon" không?
l0b0

7
Cuối cùng cũng tìm thấy tài liệu tham khảo và giải thích ": ở đầu tập lệnh": faqs.org/faqs/unix-faq/faq/part3/section-16.html
Bruce Ediger

1
hành vi khi bắt đầu với :rất kỳ lạ. tôi thấy rằng nó thực sự gây ra kịch bản được chạy với sh. trong khi bạn khởi động tập lệnh mà không có shebang ... nó cố chạy tập lệnh với bất kỳ shell nào đang chạy (vì vậy nếu bạn đang chạy, bashnó sẽ cố chạy nó như bashthể bạn có cshthì nó sẽ cố chạy nó như csh).
Trevor Boyd Smith

19

Bản :dựng sẵn đã có trong vỏ của Thompson - nó được ghi nhận cho Unix V6 vào năm 1975. Trong lớp vỏ của Thompson, :chỉ ra một nhãn cho gotolệnh. Nếu bạn không bao giờ cố gắng gọi gototrên một dòng bắt đầu bằng , dòng đó thực sự là một nhận xét.

Các Bourne shell , tổ tiên của vỏ Bourne / POSIX như chúng ta biết, không bao giờ có một gotomà tôi biết, nhưng giữ lại :như một lệnh không-op (nó đã hiện diện trong Unix V7 ).


Điểm cho nền lịch sử thông tin.
Tony Barganski

12

Tôi đã đào một tài liệu tham khảo cũ: "Môi trường lập trình UNIX" (c) 1984 của Kernighan và Pike.

Trang 147 (Lập trình Shell) nói điều này:

":" là một lệnh được tích hợp sẵn, không làm gì ngoài việc đánh giá các đối số của nó và trả về "true". Thay vào đó [đề cập đến một ví dụ về tập lệnh], chúng ta có thể đã sử dụng true , chỉ đơn thuần trả về trạng thái thoát thực sự. (Ngoài ra còn có một lệnh sai .) Nhưng ':' hiệu quả hơn đúng vì nó không thực thi một lệnh từ hệ thống tệp . [Chữ nghiêng / nhấn mạnh là của tôi.]


2
Tất nhiên, truebây giờ cũng là một phần mềm dựng sẵn trên nhiều hệ thống.
tripleee

8

Tôi dường như nhớ lại rằng các phiên bản đầu tiên của shell không có cú pháp nhận xét. Một dòng bắt đầu bằng :(có lẽ là một thực thi thực tế, tương tự /bin/true) sẽ là sự thay thế tốt nhất.

Đây là một trang dành cho người đàn ông vỏ sò cổ đại (không liên quan); không có đề cập đến bất kỳ cú pháp bình luận.


4
Nguồn gốc của :thực tế là một chỉ báo nhãn cho gotolệnh, trong một số vỏ cổ (tôi không biết cái nào). Một nhãn : somethingthực sự có thể được sử dụng như một bình luận, nếu không có kết quả khớp goto. Việc thực hành bị mắc kẹt ngay cả sau khi gotobiến mất.
Gilles 'SO- ngừng trở nên xấu xa'

8

":" Tiện dụng để gỡ lỗi.

DEBUGLOG=": debugfunction"

statement
statement
$DEBUGLOG arg1 arg2 ...
statement
statement

Chạy bình thường, chức năng gỡ lỗi không bao giờ được thực thi, vì vậy chỉ cần bước qua noop (mặc dù các biến và ký tự đại diện được mở rộng). Nếu cần gỡ lỗi sâu hơn, hãy loại bỏ noop khỏi biến và gỡ lỗi được gọi với bất kỳ đối số nào được yêu cầu.

Một cách sử dụng tiện dụng khác là nhận xét khối, đây là một tính năng còn thiếu từ cú pháp shell.

: << COMMENT
all --statements --in --here
are now -a here document which are
passed to --the noop
COMMENT
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.