Tại sao các nội dung shell shell không có trang man phù hợp?


32

Tất cả các nội dung shell chia sẻ cùng một trang hướng dẫn:

BUILTIN(1)                BSD General Commands Manual               BUILTIN(1)

NAME
     builtin, !

v.v.

Sau đó, có một văn bản nhỏ mô tả các nội dung shell là gì, và sau đó là một danh sách trông giống như thế này:

  Command       External    csh(1)    sh(1)
       !             No          No        Yes
       %             No          Yes       No

Nhưng nếu chúng ta làm, man grepchúng ta có các phần như

  • Lỗi
  • Lịch sử
  • Xem thêm
  • Tiêu chuẩn
  • Sự miêu tả

v.v.

Đừng bao builtins có lịch sử riêng, mô tả và lập luận của họ như -Ahay -r? Tại sao điều đó không được cung cấp trong các trang hướng dẫn và làm thế nào tôi học cách sử dụng chúng một cách chính xác và hiệu quả?


Câu trả lời:


25

Bởi vì nội dung là một phần của vỏ. Bất kỳ lỗi hoặc lịch sử họ có là lỗi và lịch sử của chính vỏ. Chúng không phải là các lệnh độc lập và không tồn tại bên ngoài lớp vỏ mà chúng được tích hợp.

Tương đương, bashít nhất, là helplệnh. Ví dụ:

$ help while
while: while COMMANDS; do COMMANDS; done
    Execute commands as long as a test succeeds.

    Expand and execute COMMANDS as long as the final command in the
    `while' COMMANDS has an exit status of zero.

    Exit Status:
    Returns the status of the last command executed.

Tất cả các nội dung bash có helptrang. Ngay cả helpchính nó:

$ help help
help: help [-dms] [pattern ...]
    Display information about builtin commands.

    Displays brief summaries of builtin commands.  If PATTERN is
    specified, gives detailed help on all commands matching PATTERN,
    otherwise the list of help topics is printed.

    Options:
      -d    output short description for each topic
      -m    display usage in pseudo-manpage format
      -s    output only a short usage synopsis for each topic matching
        PATTERN

    Arguments:
      PATTERN   Pattern specifiying a help topic

    Exit Status:
    Returns success unless PATTERN is not found or an invalid option is given.

Lấy cảm hứng từ sedtập lệnh của @ mikeerv , đây là một chức năng nhỏ sẽ in phần có liên quan của trang man bằng Perl. Thêm dòng này vào tệp khởi tạo shell của bạn ( ~/.bashrcđối với bash):

manperl(){ man "$1" | perl -00ne "print if /^\s*$2\b/"; }

Sau đó, bạn chạy nó bằng cách cho nó một trang man và tên của một phần:

$ manperl bash while
       while list-1; do list-2; done
       until list-1; do list-2; done
              The while command continuously executes the list list-2 as long as the last command in the list list-1 returns an exit
              status of zero.  The until command is identical to the while command, except that the test is negated; list-2 is  exe‐
              cuted  as  long  as the last command in list-1 returns a non-zero exit status.  The exit status of the while and until
              commands is the exit status of the last command executed in list-2, or zero if none was executed.

$ manperl grep SYNOPSIS
SYNOPSIS
       grep [OPTIONS] PATTERN [FILE...]
       grep [OPTIONS] [-e PATTERN | -f FILE] [FILE...]

$ manperl rsync "-r"
       -r, --recursive
              This tells rsync to copy directories recursively.  See also --dirs (-d).

2
@DisplayName họ đang bash. Họ là một phần của nó và vâng, họ được giải thích trong SHELL BUILTIN COMMANDSphần của bashtrang người đàn ông. "Trang người đàn ông" của họ là help builtin_name.
terdon

3
Điều không rõ ràng là tại sao họ không đưa ra trang con người. Các trang man chỉ là các tập tin trên MANPATH. Họ không phải tương ứng với các nhị phân riêng biệt. Về nguyên tắc, không có lý do tại sao bash không thể xuất xưởng với các trang dành cho nội dung của nó - thay vì có một hệ thống trợ giúp nội bộ.
Francis Davey

4
@FrancisDavey: Nhưng hầu hết các nội dung tồn tại (với các phần mở rộng khác nhau) trong các shell khác nhau. Các trang web không phải là vỏ cụ thể; chúng là toàn hệ thống.
2014 lúc 3:22

2
@FrancisDavey Như đã nói, các lệnh không phải là hệ thống rộng. Nó sẽ là một chút sai lệch để có một manpage cho một lệnh đó không phải hiện diện trong mỗi vỏ, nhưng thậm chí tệ hơn, nó sẽ rất khó hiểu để có một trang người đàn ông cho một lệnh đó hiện diện trong nhiều vỏ, nhưng mà ứng xử khác nhau (ví dụ như , chấp nhận các đối số khác nhau, có cú pháp khác nhau, v.v.).
Joshua Taylor

1
@mikeerv Tuy nhiên, tôi sẽ chào đón các trang man cho các nội dung shell dọc theo dòng của những gì, ví dụ: git Mời, nơi man git commitđưa ra một trang man cho git-commit. Một cái gì đó như man bash ifsẽ là tuyệt vời .
Joshua Taylor

5

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 bashnộ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 manvà thích các infotrang 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 ...)

nhập mô tả hình ảnh ở đây

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 mantrang 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ù helprấ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 Guidebộ 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 mantrang riêng cho điều đó - (tôi nghĩ rằng nó có tổng số 8 hoặc 9 zshtrang cá nhân - bao gồm cả zshallnhữ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 mantrang shell . Nhưng helplà khá tốt bashtrong hầu hết các trường hợp.

sedGầ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ỉ /./dxó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à mantrang 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

nhập mô tả hình ảnh ở đây

... 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:

nhập mô tả hình ảnh ở đây

Đâ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 \nký tự ewline sẽ bị xóa khỏi đầu ra.
    • \nký 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:indentcả hai vòng khép kín phụ thuộc lẫn nhau và là cách duy nhất để có được một \newline.
    • :printChu 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 \nký tự ewline.
    • :indentChu kỳ bắt đầu trên các dòng trống - hoặc trên :printcác dòng chu kỳ không thành công #test- nhưng :indentloại bỏ tất cả các \nchuỗi trống + ewline hàng đầu khỏi đầu ra của nó.
    • một khi :printbắ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 #testthất bại.
    • trước khi :indentbắt đầu, trước tiên, kiểm tra hkhô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à #testkhô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#testcầu hai vòng khép kín.
    • #testvượt qua khi loạt khoảng trống hàng đầu ngắn hơn chuỗi tiếp theo là \newline cuối cùng trong chuỗi dòng.
    • #matchchuẩn bị các \newlines hàng đầu cần thiết để bắt đầu một :printchu kỳ cho bất kỳ :indentchuỗ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.

2
Sed-fu của bạn là mạnh mẽ. Tất nhiên, bạn có thể làm điều tương tự với manperl(){ man $1 | perl -00ne "print if /^\s*$2\b/"; }và sau đó manperl sh SYNOPSIShoặc manperl sh read:)
terdon

@terdon - không, bạn không thể. Điều này không ăn đầu vào. Tôi có thể làm điều tương tự như sed 'H;$!d;g;s/\(\(\n *\)match\([^\n]*\)\2 \)\{1,\}\)*.\{,1\}/\1/g'... có lẽ nó hoạt động ... nhưng điều đó đòi hỏi phải nuốt tập tin và phân tích tất cả cùng một lúc. Điều này hoạt động trong một luồng - nó có thể xử lý đầu vào ở bất kỳ kích thước nào với điều kiện các dòng không dài về mặt thiên văn. Nó in như nó hoạt động - và nó phân tích tất cả các man's \backslash thoát để khởi động. Nhưng manchỉ là một ứng dụng duy nhất cho nó - Tôi cũng đã áp dụng nhiều cho các vấn đề khác ...
mikeerv

1
Tôi chỉ kéo dây chuyền của bạn vì tôi có thể làm những gì bạn mô tả với một lớp lót nhỏ. Lưu ý, tuy nhiên, nó không nuốt toàn bộ tập tin, nó hoạt động trong một luồng. Nó chỉ định nghĩa "dòng" bằng cách sử dụng \n\nthay vì \nnhưng vẫn có thể xử lý bất kỳ kích thước đầu vào và in khi nó hoạt động. Xem "chế độ đoạn văn" tại đây: perldoc.perl.org/perlrun.html
terdon

@terdon Có lẽ đó là cách tốt hơn để đến đây. Trong sedđó có thể được thực hiện như : '/./{H;$!d' -e '};x;now work the paragraph...'. Tôi cũng thường làm điều đó. Nhưng ban đầu tôi đã viết phần đầu tiên để xem nhật ký trực tiếp với thời gian không giới hạn và thậm chí hành vi đó là iffy - bộ đệm có thể phát nổ trong một số điều kiện nhất định. Đó chỉ là một nửa kích thước này - manlàm cho nó khó hơn. Mặc dù vậy, tôi đã xem xét man -Hsau khi nhận được bản mantóm tắt ở trên và tôi nghĩ rằng có thể dễ dàng hơn khi làm việc với HTML được cài đặt bằng máy mà groff có thể in trên các hệ thống GNU. Tôi là một khuỷu tay sâu thẳm đã
trở nên khó khăn

@terdon - Tôi đã tự mình đoán thứ hai và thử một cách tiếp cận tập trung vào đoạn văn, nhưng nó dễ dàng hơn. Điều này được phần. Giống như mansed cmd DESCRIPTIONđược phần MÔ TẢ - và tất cả những phần được bao gồm. Một tìm kiếm phù hợp được in toàn bộ và như thể mức độ thụt lề của nó là đầu trang. Nó thậm chí bỏ qua các kết quả dương tính giả bằng cách bỏ qua các đoạn phù hợp nhưng sau đó không thụt lề thêm. Nó phù hợp với các đối số của nó thông qua các khoảng trống màu thoát ra và không xử lý chúng cho đến khi nó chắc chắn sẵn sàng để in một dòng. Tất cả điều đó là rất khó đối với tôi để làm với nhiều dữ liệu hơn một dòng tại một thời điểm.
mikeerv

1

Mỗi vỏ có tập hợp riêng của nó. Mặc dù có những điểm tương đồng, nhưng mỗi cái đều có những đặc thù riêng cần được ghi lại.

Trên các hệ thống như Linux và FreeBSD (và OSX, kế thừa từ FreeBSD) trong đó mỗi shell được cung cấp dưới dạng một gói riêng biệt, không có trang man nào cho nội dung; thay vào đó, mỗi nội dung được ghi lại trong trang man của shell. Vì vậy, hãy đọc trang bash man để biết tài liệu về killnội dung của bash , đọc trang man dash cho tài liệu về killnội dung của dash , v.v. Ngoài ra còn có một trang dành cho killtiện ích độc lập.

Xem Tôi có thể lấy các trang cá nhân cho các lệnh dựng sẵn bash không? cho một manhàm hiển thị tài liệu nội bộ của bash thay vì trang man nếu đối số là tên của nội dung.

Có các biến thể unix cung cấp các trang man cho các nội dung shell - trên thực tế, hầu hết các biến thể thương mại đều có. Điều đó khả thi vì hệ thống đi kèm với một vỏ duy nhất hoặc một bộ vỏ đã biết. Trang người đàn ông thảo luận về sự khác biệt giữa các vỏ. Ví dụ, fg(1)trang người đàn ông trên Solaris 10 có phần cho sh, kshcsh. Các fg(1)trang người đàn ông trên AIX 7.1 tài liệu tham khảo “Korn shell” và “POSIX vỏ” nhưng thảo luận chúng lại với nhau (chúng xảy ra để hỗ trợ chính xác các tính năng tương tự cho fg). Các fg(1)trang người đàn ông trên Tru64 5,0 thảo luận các ksh dựng sẵn và ám chỉ người dùng csh đến csh(1)trang người đàn ông. SCOrõ ràng đi kèm với một vỏ duy nhất. Bạn có thể cài đặt các shell khác dưới dạng các gói bổ sung trên các hệ điều hành này; nếu bạn sử dụng trình bao tùy chỉnh, bạn phải nhớ rằng các trang man cho nội trang sẽ không có liên quan khi sử dụng trình bao không mặc định.

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.