Mặc dù sự thật là một số nội dung shell có thể có một số ít hiển thị trong một hướng dẫn hoàn chỉnh - đặc biệt là đối với các bash
nội dung cụ thể mà bạn chỉ có thể sử dụng trên hệ thống GNU (theo quy tắc của GNU, không tin vào man
và thích các info
trang riêng của họ ) - phần lớn các tiện ích POSIX - tích hợp shell hay nói cách khác - được thể hiện rất tốt trong Hướng dẫn của Lập trình viên POSIX.
Đây là một đoạn trích từ dưới cùng của tôi man sh
(có lẽ dài 20 trang hoặc hơn ...)
Tất cả những người đang có, và những người khác không được đề cập như set
, read
, break
... tốt, tôi không cần phải đặt tên cho tất cả chúng. Nhưng lưu ý (1P)
ở phía dưới bên phải - nó biểu thị loạt hướng dẫn POSIX loại 1 - đó là những man
trang tôi đang nói đến.
Nó có thể là bạn chỉ cần cài đặt một gói? Điều này có vẻ hứa hẹn cho một hệ thống Debian. Mặc dù help
rất hữu ích, nhưng nếu bạn có thể tìm thấy nó, bạn chắc chắn nên có được POSIX Programmer's Guide
bộ truyện đó . Nó có thể cực kỳ hữu ích. Và nó là trang cấu thành rất chi tiết.
Ngoài ra, các phần tử shell hầu như luôn được liệt kê trong một phần cụ thể của hướng dẫn sử dụng shell cụ thể. zsh
, ví dụ, có toàn bộ một man
trang riêng cho điều đó - (tôi nghĩ rằng nó có tổng số 8 hoặc 9 zsh
trang cá nhân - bao gồm cả zshall
những trang rất lớn.)
Tất nhiên bạn có thể grep
man
:
man bash 2>/dev/null |
grep '^[[:blank:]]*read [^`]*[-[]' -A14
read [-ers] [-a aname] [-d delim] [-i text] [-n
nchars] [-N nchars] [-p prompt] [-t timeout] [-u
fd] [name ...]
One line is read from the standard input, or
from the file descriptor fd supplied as an
argument to the -u option, and the first
word is assigned to the first name, the sec‐
ond word to the second name, and so on, with
leftover words and their intervening separa‐
tors assigned to the last name. If there
are fewer words read from the input stream
than names, the remaining names are assigned
empty values. The characters in IFS are
used to split the line into words using the
same rules the shell uses for expansion
... Nó khá gần với những gì tôi từng làm khi tìm kiếm man
trang shell . Nhưng help
là khá tốt bash
trong hầu hết các trường hợp.
sed
Gần đây tôi đã thực hiện một kịch bản để xử lý loại công cụ này. Đó là cách tôi lấy phần trong hình trên. Nó vẫn dài hơn tôi muốn, nhưng nó đang được cải thiện - và có thể khá tiện dụng. Trong lần lặp hiện tại của nó, nó sẽ trích xuất một cách đáng tin cậy một phần văn bản có ngữ cảnh phù hợp với một phần hoặc tiêu đề phụ dựa trên [a] mẫu [s] được đưa ra trên dòng lệnh. Nó tô màu đầu ra của nó và in ra thiết bị xuất chuẩn.
Nó hoạt động bằng cách đánh giá mức độ thụt lề. Các dòng đầu vào không trống thường bị bỏ qua, nhưng khi nó gặp một dòng trống, nó bắt đầu chú ý. Nó tập hợp các dòng từ đó cho đến khi nó xác minh rằng chuỗi hiện tại chắc chắn thụt vào sâu hơn so với dòng đầu tiên của nó trước khi một dòng trống khác xảy ra nếu không nó sẽ bỏ luồng và chờ trống tiếp theo. Nếu thử nghiệm thành công, nó sẽ cố gắng khớp dòng chì với đối số dòng lệnh của nó.
Điều này có nghĩa rằng một trận đấu mẫu sẽ phù hợp:
heading
match ...
...
...
text...
..và ..
match
text
..nhưng không..
heading
match
match
notmatch
..hoặc là..
text
match
match
text
more text
Nếu một trận đấu có thể có nó bắt đầu in. Nó sẽ loại bỏ các khoảng trống hàng đầu của dòng phù hợp khỏi tất cả các dòng mà nó in - vì vậy, bất kể mức độ thụt lề, nó tìm thấy dòng trên nó in như thể nó ở trên cùng. Nó sẽ tiếp tục in cho đến khi nó gặp một dòng khác ở mức bằng hoặc thấp hơn mức thụt lề so với dòng phù hợp của nó - vì vậy toàn bộ các phần được lấy chỉ bằng một trận đấu tiêu đề, bao gồm bất kỳ / tất cả các phần, đoạn mà chúng có thể chứa.
Vì vậy, về cơ bản, nếu bạn yêu cầu nó khớp với một mẫu, nó sẽ chỉ làm như vậy đối với một tiêu đề chủ đề thuộc loại nào đó và sẽ tô màu và in tất cả các văn bản mà nó tìm thấy trong phần được khớp bởi nó. Không có gì được lưu khi thực hiện điều này ngoại trừ thụt dòng đầu tiên của bạn - và do đó, nó có thể rất nhanh và xử lý \n
đầu vào được phân tách bằng ewline với hầu hết mọi kích thước.
Tôi đã mất một lúc để tìm ra cách tái diễn vào các tiêu đề phụ như sau:
Section Heading
Subsection Heading
Nhưng cuối cùng tôi đã sắp xếp nó ra.
Tôi đã phải làm lại toàn bộ cho đơn giản, mặc dù. Mặc dù trước đây tôi có một số vòng lặp nhỏ thực hiện hầu hết các thao tác giống nhau theo các cách hơi khác nhau để phù hợp với bối cảnh của chúng, bằng cách thay đổi phương thức đệ quy của chúng, tôi đã quản lý để sao chép lại phần lớn mã. Bây giờ có hai vòng lặp - một bản in và một kiểm tra thụt lề. Cả hai đều phụ thuộc vào cùng một bài kiểm tra - vòng lặp in bắt đầu khi bài kiểm tra đi qua và vòng thụt lề tiếp quản khi nó thất bại hoặc bắt đầu trên một dòng trống.
Toàn bộ quá trình diễn ra rất nhanh bởi vì hầu hết thời gian nó chỉ /./d
xóa bất kỳ dòng không trống nào và chuyển sang dòng tiếp theo - ngay cả kết quả từ việc zshall
điền vào màn hình ngay lập tức. Điều này đã không thay đổi.
Dù sao, nó rất hữu ích cho đến nay, mặc dù. Ví dụ, read
điều trên có thể được thực hiện như sau:
mansed bash read
... Và nó có được toàn bộ khối. Nó có thể lấy bất kỳ mẫu hoặc bất cứ điều gì, hoặc nhiều đối số, mặc dù đầu tiên luôn là man
trang mà nó sẽ tìm kiếm. Đây là hình ảnh của một số đầu ra của nó sau khi tôi đã làm:
mansed bash read printf
... cả hai khối được trả lại toàn bộ. Tôi thường sử dụng nó như:
mansed ksh '[Cc]ommand.*'
... Mà nó khá hữu ích. Ngoài ra, nhận được SYNOPS[ES]
làm cho nó thực sự tiện dụng:
Đây là nếu bạn muốn cho nó một vòng xoáy - Tôi sẽ không đổ lỗi cho bạn nếu bạn không mặc dù.
mansed() {
MAN_KEEP_FORMATTING=1 man "$1" 2>/dev/null | ( shift
b='[:blank:]' s='[:space:]' bs=$(printf \\b) esc=$(printf '\033\[') n='\
' match=$(printf "\([${b}]*%s[${b}].*\)*" "$@")
sed -n "1p
/\n/!{ /./{ \$p;d
};x; /.*\n/!g;s///;x
:indent
/.*\n\n/{s///;x
};n;\$p;
/^\([^${s}].*\)*$/{s/./ &/;h; b indent
};x; s/.*\n[^-[]*\n.*//; /./!x;t
s/[${s}]*$//; s/\n[${b}]\{2,\}/${n} /;G;h
};
#test
/^\([${b}]*\)\([^${b}].*\n\)\1\([${b}]\)/!b indent
s//\1\2.\3/
:print
/^[${s}]*\n\./{ s///;s/\n\./${n}/
/${bs}/{s/\n/ & /g;
s/\(\(.\)${bs}\2\)\{1,\}/${esc}38;5;35m&${esc}0m/g
s/\(_${bs}[^_]\)\{1,\}/${esc}38;5;75m&${esc}0m/g
s/.${bs}//g;s/ \n /${n}/g
s/\(\(${esc}\)0m\2[^m]*m[_ ]\{,2\}\)\{2\}/_/g
};p;g;N;/\n$/!D
s//./; t print
};
#match
s/\n.*/ /; s/.${bs}//g
s/^\(${match}\).*/${n}\1/
/../{ s/^\([${s}]*\)\(.*\)/\1${n}/
x; s//${n}\1${n}. \2/; P
};D
");}
Tóm lại, quy trình làm việc là:
- bất kỳ dòng nào không trống và không chứa
\n
ký tự ewline sẽ bị xóa khỏi đầu ra.
\n
ký tự ewline không bao giờ xảy ra trong không gian mẫu đầu vào. Họ chỉ có thể có được như là kết quả của một chỉnh sửa.
:print
và :indent
cả hai vòng khép kín phụ thuộc lẫn nhau và là cách duy nhất để có được một \n
ewline.
:print
Chu kỳ vòng lặp bắt đầu nếu các ký tự đầu trên một dòng là một chuỗi các khoảng trống theo sau là một \n
ký tự ewline.
:indent
Chu kỳ bắt đầu trên các dòng trống - hoặc trên :print
các dòng chu kỳ không thành công #test
- nhưng :indent
loại bỏ tất cả các \n
chuỗi trống + ewline hàng đầu khỏi đầu ra của nó.
- một khi
:print
bắt đầu, nó sẽ tiếp tục kéo các dòng đầu vào, tước khoảng trắng hàng đầu lên đến số lượng tìm thấy trên dòng đầu tiên trong chu kỳ của nó, dịch overstrike và understrike backspace thoát ra khỏi thiết bị đầu cuối màu và in kết quả cho đến khi #test
thất bại.
- trước khi
:indent
bắt đầu, trước tiên, kiểm tra h
không gian cũ xem có tiếp tục thụt lề có thể (chẳng hạn như Tiểu mục) không , sau đó tiếp tục kéo đầu vào miễn là #test
không thành công và bất kỳ dòng nào tiếp theo khớp đầu tiên tiếp tục khớp [-
. Khi một dòng sau mẫu đầu tiên không khớp với mẫu đó, nó sẽ bị xóa - và sau đó là tất cả các dòng tiếp theo cho đến dòng trống tiếp theo.
#match
và #test
cầu hai vòng khép kín.
#test
vượt qua khi loạt khoảng trống hàng đầu ngắn hơn chuỗi tiếp theo là \n
ewline cuối cùng trong chuỗi dòng.
#match
chuẩn bị các \n
ewlines hàng đầu cần thiết để bắt đầu một :print
chu kỳ cho bất kỳ :indent
chuỗi đầu ra nào dẫn đến khớp với bất kỳ đối số dòng lệnh nào. Các chuỗi không được hiển thị trống - và dòng trống kết quả được chuyển trở lại :indent
.