Tại sao khoảng cách giữa các tùy chọn và tham số có thể được bỏ qua?


16

Ví dụ:

xargs -n 1

giống như

xargs -n1

Nhưng nếu bạn nhìn vào trang man , tùy chọn được liệt kê là -n max-args, điều đó có nghĩa là không gian được cho là được bảo tồn. Không có gì về dạng viết tắt -n max-args .

Điều này cũng xảy ra với nhiều tiện ích Linux khác.

Cái này được gọi là gì trong Linux? Có phải tất cả các tiện ích đều hỗ trợ mẫu viết tắt (nhưng không bao giờ ghi lại nó trong trang man)?


1
12.1.2.a là một số lịch sử; Tôi thề đã có một câu hỏi hay ở đây về điều này nhưng tôi chưa tìm thấy nó.

2
@drewbenn câu hỏi khác mà bạn nghĩ có thể là của tôi: unix.stackexchange.com/q/188046/41515

Câu trả lời:


12

Khi bạn viết bit phân tích dòng lệnh của mã, bạn chỉ định tùy chọn nào lấy đối số và tùy chọn nào không. Ví dụ: trong tập lệnh shell chấp nhận một -htùy chọn (ví dụ như trợ giúp) và một -atùy chọn cần lấy một đối số, bạn làm

opt_h=0     # default value
opt_a=""

while getopts 'a:h' opt; do
    case $opt in
        h)  opt_h=1 ;;
        a)  opt_a="$OPTARG" ;;
    esac
done

echo "h: $opt_h"
echo "a: $opt_a"

Các a:hchút nói: "Tôi đang mong đợi để phân tích hai lựa chọn, -a-h, và -anên một cuộc tranh cãi" (đó là :sau ađó nói với các phân tích cú pháp mà -aphải mất một đối số).

Do đó, không bao giờ có bất kỳ sự mơ hồ nào trong đó một tùy chọn kết thúc, nơi giá trị của nó bắt đầu và nơi một tùy chọn khác bắt đầu sau đó.

Chạy nó:

$ bash test.sh -h -a hello
h: 1
a: hello

$ bash test.sh -h -ahello
h: 1
a: hello

$ bash test.sh -hahello
h: 1
a: hello

Đây là lý do tại sao bạn hầu như không nên viết trình phân tích cú pháp dòng lệnh của riêng bạn để phân tích các tùy chọn.

Chỉ có một trường hợp trong ví dụ này là khó khăn. Việc phân tích cú pháp thường dừng ở tùy chọn không phải tùy chọn đầu tiên, vì vậy khi bạn có nội dung trên dòng lệnh trông giống như tùy chọn:

$ bash test.sh -a hello -world
test.sh: illegal option -- w
test.sh: illegal option -- o
test.sh: illegal option -- r
test.sh: illegal option -- l
test.sh: illegal option -- d
h: 0
a: hello

Sau đây giải quyết rằng:

$ bash test.sh -a hello -- -world
h: 0
a: hello

Các --tín hiệu kết thúc các tùy chọn dòng lệnh và -worldbit còn lại để chương trình thực hiện bất cứ điều gì nó muốn (nó nằm trong một trong các biến vị trí).

Nhân tiện, đó là cách bạn loại bỏ một tệp có dấu gạch ngang khi bắt đầu tên tệp của nó rm.

CHỈNH SỬA :

Các tiện ích được viết bằng C gọi getopt()(khai báo unistd.h) hoạt động khá giống nhau. Trong thực tế, đối với tất cả chúng ta đều biết, các bashchức năng getoptscó thể được thực hiện bằng một cuộc gọi đến các chức năng thư viện C getopt(). Perl, Python và các ngôn ngữ khác có thư viện phân tích cú pháp dòng lệnh tương tự và rất có thể chúng thực hiện phân tích cú pháp theo cách tương tự.

Một số trong những thói quen thư viện getoptgetoptgiống như này cũng xử lý các tùy chọn "dài". Chúng thường được bắt đầu bằng dấu gạch ngang kép ( --) và các tùy chọn dài có các đối số thường làm như vậy sau một dấu bằng, ví dụ --block-size=SIZEtùy chọn [một số triển khai] dutiện ích (cũng cho phép -B SIZEchỉ định điều tương tự).

Các hướng dẫn lý do thường được viết để hiển thị một khoảng trống ở giữa các tùy chọn ngắn và các đối số của chúng có lẽ là để dễ đọc.

EDIT : Các công cụ thực sự cũ, chẳng hạn như ddtarcác tiện ích, có các tùy chọn mà không có dấu gạch ngang trước mặt chúng. Điều này hoàn toàn là vì lý do lịch sử và để duy trì khả năng tương thích với phần mềm dựa vào chúng để hoạt động chính xác theo cách đó. Các tartiện ích đã đạt được khả năng chụp tùy chọn với dấu gạch ngang trong thời gian gần đây hơn. Hướng dẫn sử dụng BSD để targọi các tùy chọn kiểu cũ cho "cờ được gói".


Tính năng này có vẻ dễ thực hiện trong kịch bản bash. Nhưng tôi nghĩ rằng hầu hết các tiện ích được viết bằng C (sau đó được biên dịch thành nhị phân) không bash. Tại sao các tiện ích này thực hiện tính năng này?
J.Joe

@ J.Joe Bởi vì họ gọi getopt()(khai báo unistd.h), điều này cũng làm điều tương tự.
Kusalananda

2
Đúng, bạn đúng. Tham khảo . Điều này cũng giải quyết một bí ẩn khác mà các tùy chọn có thể được kết hợp -a -b=== -ab
J.Joe

1
Các đối số tùy chọn cho các cờ sẽ tạo ra sự mơ hồ, do đó chúng không thể được kết hợp (nếu -acó đối số tùy chọn, -abkhông giống như -a -b). GNU getopt không dừng xử lý cờ khi gặp cờ không: thay vào đó (theo mặc định), thay vào đó, nó chia sẻ lại các cờ ở phía trước argv.
ilkkachu

@ilkkachu Cảm ơn đã làm rõ. Tôi có thể cập nhật câu trả lời của tôi sau.
Kusalananda

4

xargslà một trong những tiện ích POSIX. Như nhận xét của @drewbenn, POSIX ghi lại hành vi phân tích tùy chọn cho hầu hết các tiện ích của nó để phù hợp getopt, với một số khoản phụ cấp cho các triển khai khác, nói trong Cú pháp đối số tiện ích 12.1 :

Phần này mô tả cú pháp đối số của các tiện ích tiêu chuẩn và giới thiệu thuật ngữ được sử dụng trong suốt POSIX.1-2008 để mô tả các đối số được xử lý bởi các tiện ích.

Trong POSIX.1-2008, một ký hiệu đặc biệt được sử dụng để mô tả cú pháp của các đối số của tiện ích. Trừ khi có ghi chú khác , tất cả các mô tả tiện ích đều sử dụng ký hiệu này, được minh họa bằng ví dụ này (xem Lệnh đơn giản XCU ):

và kết luận với

Tất cả các tiện ích và ứng dụng trong tương lai nên sử dụng các hướng dẫn này để nâng cao tính di động của người dùng. Việc một số tiện ích lịch sử không thể thay đổi (để tránh phá vỡ các ứng dụng hiện có) không nên ngăn cản mục tiêu trong tương lai này.

Trong POSIX (hãy nhớ rằng nó chỉ bao gồm các tiện ích được sử dụng phổ biến nhất), có những trường hợp ngoại lệ vượt qua toán hạng sẽ là tùy chọn trong các tiện ích khác như tham số vị trí hoặc tham số có cú pháp đặc biệt :

POSIX cho phép các giá trị tùy chọn tùy chọn:

Các đối số tùy chọn được hiển thị tách biệt với các tùy chọn của chúng theo các <blank>ký tự, ngoại trừ khi đối số tùy chọn được đặt trong ký hiệu '['']'ký hiệu để chỉ ra rằng đó là tùy chọn.

Chính thức, tôi không nhớ các tiện ích POSIX nào sử dụng tính năng này. Các tiện ích ticinfocmptiện ích sử dụng tính năng cho các cấp độ của -vtùy chọn (dài dòng / gỡ lỗi).

Điểm cụ thể mà bạn đã hỏi là chi tiết trong phần còn lại của đoạn đó, diễn ra trên một vài dòng.

Trước POSIX, một số triển khai các pstùy chọn được chấp nhận mà không có dấu gạch nối hàng đầu. Mô tả POSIX không đề cập đến điều đó trong phần mô tả về tiện ích hoặc trong cơ sở cú pháp:

Ngoài POSIX, còn có các triển khai tùy chọn dài (như GNU getopt_long hoặc X Toolkit ), sử dụng nhiều cách khác nhau để tách hoặc nối giá trị của tùy chọn với tùy chọn. Ví dụ, dấu câu có thể được sử dụng:

--option=value
--option value

Tùy thuộc vào việc triển khai, một dấu gạch ngang kép có thể / có thể không được sử dụng để phân biệt các tùy chọn dài với ngắn (getopt): lynx và X Toolkit sử dụng một dấu gạch ngang đơn; GNU getopt_longsử dụng dấu gạch ngang kép chẳng hạn. Ngoài ra, một +có thể được sử dụng để chỉ ra rằng một tùy chọn bị phủ định.

Mô tả của POSIX dường như không đề cập đến bất kỳ điều nào trong số này, nhưng bạn chắc chắn sẽ gặp phải chúng.


Được -option=valuecho là --option=value? (Định dạng tùy chọn dài, hai dấu gạch ngang ở đầu thay vì một)
J.Joe

Một vài tiện ích kế thừa sử dụng các tùy chọn dài một dấu gạch ngang (-option) nhưng phần lớn chúng không được dùng cho các tập lệnh và chương trình mới. Sử dụng một dấu gạch ngang cho các tùy chọn ngắn như được xử lý bởi getopt. Hầu như tất cả các tập lệnh và chương trình mới sử dụng các tùy chọn dài gấp đôi. Nhiều người cũng hỗ trợ tương đương tùy chọn ngắn một gạch ngang cho những cái được sử dụng phổ biến nhất. Các tùy chọn dài làm cho mã kịch bản tự viết nhiều hơn, cần ít bình luận hơn.
DocSalvager
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.