Dlaczego wbudowane powłoki nie mają odpowiednich stron podręcznika?


32

Wszystkie wbudowane powłoki współużytkują tę samą stronę podręcznika:

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

NAME
     builtin, !

itp.

Następnie jest krótki tekst opisujący, jakie są wbudowane powłoki, a następnie lista, która wygląda mniej więcej tak:

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

Ale jeśli to zrobimy man grep, otrzymamy sekcje takie jak

  • Robaki
  • Historia
  • Zobacz też
  • Standardy
  • Opis

itp.

Czy wbudowane powłoki nie mają własnej historii, opisu i argumentów takich jak -Alub -r? Dlaczego nie ma tego na stronach podręcznika i jak mam nauczyć się korzystać z nich poprawnie i wydajnie?


Odpowiedzi:


25

Ponieważ wbudowane są częścią powłoki. Wszelkie błędy lub historia, które mają, są błędami i historią samej powłoki. Nie są to niezależne polecenia i nie istnieją poza powłoką, w której są wbudowane.

Ekwiwalent, na bashco najmniej to helppolecenie. Na przykład:

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

Wszystkie wbudowane bash mają helpstrony. Nawet helpsam:

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

Zainspirowany skryptem @ mikeserv sed, oto mała funkcja, która wydrukuje odpowiednią sekcję strony podręcznika przy użyciu Perla. Dodaj ten wiersz do pliku inicjalizacji powłoki ( ~/.bashrcdla bash):

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

Następnie uruchamiasz go, nadając mu stronę podręcznika i nazwę sekcji:

$ 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 oni bash. Są częścią tego i tak, zostały wyjaśnione w SHELL BUILTIN COMMANDSsekcji strony podręcznika bash. Ich „stronami podręcznika” są help builtin_name.
terdon

3
Nie jest jasne, dlaczego nie otrzymali stron podręcznika użytkownika. Strony podręcznika są tylko plikami w MANPATH. Nie muszą odpowiadać oddzielnym plikom binarnym. Zasadniczo nie ma powodu, dla którego bash nie mógłby zostać dostarczony ze stronami podręcznika użytkownika dla jego wbudowanych funkcji - zamiast mieć wewnętrzny system pomocy.
Francis Davey

4
@FrancisDavey: Ale większość poleceń wbudowanych istnieje (z różnymi rozszerzeniami) w różnych powłokach. Strony podręcznika nie są specyficzne dla powłoki; są ogólnosystemowe.
rici,

2
@FrancisDavey Jak powiedziała rici, polecenia nie są dostępne w całym systemie. Byłoby nieco mylące mieć stronę podręczną dla polecenia, która nie jest obecna w każdej powłoce, ale co gorsza, byłoby bardzo mylące mieć stronę podręcznika dla polecenia, które jest obecne w wielu powłokach, ale które zachowuje się inaczej (np. , akceptuje różne argumenty, ma inną składnię itp.).
Joshua Taylor

1
@mikeserv Jednak byłoby mile widziane strony man dla powłoki poleceń wbudowanych wzdłuż linii co np git oferty, gdzie man git commitprowadzi do strony man git-commit. Coś takiego man bash ifbyłoby cudowne .
Joshua Taylor

5

Chociaż prawdą jest, że niektóre wbudowane powłoki mogą mieć skąpe wyświetlanie w kompletnym podręczniku - szczególnie dla tych bashspecyficznych wbudowanych, których prawdopodobnie używasz tylko w systemie GNU (ludzie GNU z reguły nie wierzą w mani wolą własne infostrony) - zdecydowana większość narzędzi POSIX - wbudowane powłoki lub inne - są bardzo dobrze reprezentowane w POSIX Programmer's Guide.

Oto fragment z dołu mojego man sh (który prawdopodobnie ma około 20 stron ...)

wprowadź opis zdjęcia tutaj

Wszystkie te istnieją, a inne nie wymienione, takie jak set, read, break... dobrze, nie trzeba ich wszystkich wymienić. Ale zwróć uwagę (1P)na prawy dolny róg - oznacza serię instrukcji POSIX kategorii 1 - to manstrony, o których mówię.

Być może wystarczy zainstalować pakiet? To wygląda obiecująco dla systemu Debian. Chociaż helpjest przydatny, jeśli możesz go znaleźć, zdecydowanie powinieneś dostać tę POSIX Programmer's Guideserię. To może być bardzo pomocne. I jego strony składowe są bardzo szczegółowe.

Poza tym wbudowane powłoki są prawie zawsze wymienione w konkretnej części podręcznika powłoki. zsh, na przykład ma całą osobną manstronę do tego - (myślę, że wynosi 8 lub 9 osobnych zshstron - w tym zshallktóra jest ogromna).

Możesz grep manoczywiście:

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

... co jest bardzo podobne do tego, co robiłem podczas przeszukiwania manstrony powłoki . Ale w większości przypadków helpjest całkiem dobry bash.

sedOstatnio pracowałem nad skryptem do obsługi tego rodzaju rzeczy. W ten sposób złapałem sekcję na powyższym obrazku. Jest jeszcze dłuższy niż lubię, ale poprawia się - i może być całkiem przydatny. W bieżącej iteracji całkiem niezawodnie wyodrębni kontekstową sekcję tekstu dopasowaną do nagłówka sekcji lub podsekcji na podstawie wzorca [a] podanego w wierszu poleceń. Koloruje wydruki i drukuje na standardowym ekranie.

Działa poprzez ocenę poziomów wcięć. Niepuste linie wejściowe są na ogół ignorowane, ale gdy napotka pustą linię, zaczyna zwracać uwagę. Stamtąd zbiera linie, dopóki nie zweryfikuje, że bieżąca sekwencja zdecydowanie wcina się dalej niż pierwsza linia, zanim pojawi się kolejna pusta linia, albo upuści wątek i czeka na następny pusty wiersz. Jeśli test się powiedzie, próbuje dopasować linię wiodącą do argumentów wiersza poleceń.

Oznacza to, że mecz wzorca pasują:

heading
    match ...
    ...
    ...
        text...

..i..

match
   text

..ale nie..

heading
    match
    match

    notmatch

..lub..

         text

         match
         match
         text

         more text

Jeśli można dopasować, rozpocznie się drukowanie. Spowoduje to usunięcie wiodących odstępów dopasowanej linii ze wszystkich drukowanych linii - więc bez względu na poziom wcięcia, który znalazł, linia na nim drukuje go tak, jakby znajdowała się na górze. Będzie kontynuował drukowanie, dopóki nie napotka innej linii na poziomie równym lub mniejszym niż wcięcie niż dopasowana linia - więc całe sekcje są chwytane tylko z dopasowaniem nagłówka, w tym wszystkie / wszystkie podsekcje, akapity, które mogą zawierać.

Zasadniczo, jeśli poprosisz go o dopasowanie wzoru, zrobi to tylko w odniesieniu do jakiegoś nagłówka tematu i pokoloruje i wydrukuje cały tekst, który znajdzie w sekcji, której nagłówek odpowiada. Nic nie jest zapisywane, ponieważ robi to, z wyjątkiem wcięcia w pierwszym wierszu - dzięki czemu może być bardzo szybki i obsługiwać \ndane oddzielone ewline praktycznie dowolnego rozmiaru.

Chwilę zajęło mi wymyślenie, w jaki sposób powrócić do podtytułów, takich jak:

Section Heading
    Subsection Heading

Ale w końcu to rozwiązałem.

Jednak dla uproszczenia musiałem to wszystko przerobić. Podczas gdy wcześniej miałem kilka małych pętli wykonujących głównie te same rzeczy w nieco inny sposób, aby dopasować się do ich kontekstu, zmieniając sposoby rekurencji udało mi się zduplikować większość kodu. Teraz są dwie pętle - jedna drukuje, a druga sprawdza wcięcie. Oba zależą od tego samego testu - pętla drukująca rozpoczyna się po przejściu testu, a pętla wcięcia przejmuje kontrolę, gdy kończy się niepowodzeniem lub zaczyna się od pustej linii.

Cały proces jest bardzo szybki, ponieważ przez większość czasu po prostu /./dusuwa niepustą linię i przechodzi do następnego - nawet wyniki zshallnatychmiastowego zapełniania ekranu. To się nie zmieniło.

W każdym razie jest to bardzo przydatne. Na przykład readpowyższe czynności można wykonać w następujący sposób:

mansed bash read

... i dostaje cały blok. Może przyjmować dowolne wzorce lub cokolwiek, lub wiele argumentów, chociaż pierwszy to zawsze manstrona, na której powinien szukać. Oto zdjęcie niektórych jego wyników po tym, jak to zrobiłem:

mansed bash read printf

wprowadź opis zdjęcia tutaj

... oba bloki są zwracane w całości. Często używam go w następujący sposób:

mansed ksh '[Cc]ommand.*'

... do czego jest całkiem użyteczny. Ponadto uzyskiwanie SYNOPS[ES]sprawia, że ​​jest to naprawdę przydatne:

wprowadź opis zdjęcia tutaj

Oto, jeśli chcesz dać mu wir - nie obwiniam cię, jeśli tego nie zrobisz.

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
");}

W skrócie, przepływ pracy to:

  • każdy wiersz, który nie jest pusty i nie zawiera \nznaku ewline, jest usuwany z wyniku.
    • \nznaki ewline nigdy nie występują w wejściowym obszarze wzorca. Można je uzyskać tylko w wyniku edycji.
  • :printi :indentoba są wzajemnie zależnymi zamkniętymi pętlami i są jedynym sposobem na uzyskanie \newline.
    • :printCykl pętli rozpoczyna się, jeśli wiodącymi znakami w linii są ciągi \nodstępów, po których następuje znak ewline.
    • :indentCykl rozpoczyna się na pustych liniach - lub na :printliniach cyklicznych, które zawodzą #test- ale :indentusuwa wszystkie wiodące puste \nsekwencje + ewline z jego wyniku.
    • gdy :printzacznie, nadal będzie ciągnąć linie wejściowe, usuwać wiodące białe znaki do wartości znalezionej na pierwszym wierszu w swoim cyklu, tłumaczyć przeciążenie przecięcia i cofnięcia podskoku na kolorowe zaciski i drukować wyniki aż do #testniepowodzenia.
    • przed :indentrozpoczęciem najpierw sprawdza hstare miejsce pod kątem ewentualnej kontynuacji wcięcia (takiego jak podsekcja) , a następnie kontynuuje pobieranie danych wejściowych tak długo, jak długo #testkończy się niepowodzeniem, a dowolna linia następująca po pierwszej kontynuuje dopasowanie [-. Gdy wiersz po pierwszym nie pasuje do tego wzorca, jest usuwany - a następnie wszystkie kolejne wiersze aż do następnej pustej linii.
  • #matchi #testzmostkuj dwie zamknięte pętle.
    • #testprzechodzi, gdy wiodąca seria \nodstępów jest krótsza niż seria, po której następuje ostatnia ewline w sekwencji linii.
    • #matchprzygotowuje wiodące \newline potrzebne do rozpoczęcia :printcyklu do dowolnej :indentsekwencji wyjściowej, która prowadzi z dopasowaniem do dowolnego argumentu wiersza poleceń. Sekwencje, które nie są renderowane jako puste - i wynikowy pusty wiersz jest przekazywany z powrotem do :indent.

2
Twój sed-fu jest silny. Oczywiście możesz zrobić to samo, manperl(){ man $1 | perl -00ne "print if /^\s*$2\b/"; }a potem manperl sh SYNOPSISlub manperl sh read:)
terdon

@terdon - nie, nie możesz. To nie zjada wkładu. Mógłbym zrobić to samo co sed 'H;$!d;g;s/\(\(\n *\)match\([^\n]*\)\2 \)\{1,\}\)*.\{,1\}/\1/g'... pewnie to działa ... ale to wymaga połknięcia pliku i parsowania go naraz. Działa to w strumieniu - może obsłużyć dane wejściowe o dowolnym rozmiarze, pod warunkiem, że linie nie są astronomicznie długie. Drukuje jak to działa - i analizuje wszystkie man„s \backslash ucieka do rozruchu. Ale manto tylko jedna aplikacja - zastosowałem wiele z nich również do innych problemów ...
mikeserv

1
Po prostu szarpię twój łańcuch, ponieważ mogę robić to, co opisujesz za pomocą małego liniowca. Pamiętaj jednak, że nie połyka pliku w całości, działa w strumieniu. Po prostu definiuje „linie” za pomocą \n\nzamiast, \nale nadal może obsłużyć dane wejściowe dowolnego rozmiaru i drukuje, gdy to działa. Zobacz „tryb akapitowy” tutaj: perldoc.perl.org/perlrun.html
terdon

@terdon Może to byłby lepszy sposób, aby przejść tutaj. W sednim można zrobić tak: '/./{H;$!d' -e '};x;now work the paragraph...'. Często też to robię. Ale pierwotnie napisałem pierwszą część do oglądania dziennika na żywo przez nieograniczoną ilość czasu, a nawet to zachowanie było niepewne - bufor może wybuchnąć pod pewnymi warunkami. To tylko połowa tego rozmiaru - manto utrudniło. Spojrzałem jednak man -Hpo otrzymaniu manpowyższego podsumowania i myślę, że może być łatwiej pracować z generowanym maszynowo językiem HTML, który groff może wydrukować w systemach GNU. Jestem trochę jak łokieć już ty
mikeserv

@terdon - sam zgadywałem i spróbowałem podejścia skoncentrowanego na akapicie, ale tak jest łatwiej. To dostaje sekcje. Jak mansed cmd DESCRIPTIONpobiera sekcja OPIS - i wszystkie zawarte. Dopasowane wyszukiwanie jest drukowane w całości i tak, jakby jego poziom wcięcia był najwyższy. Pomija nawet fałszywe alarmy, ignorując pasujące akapity, ale nie wcina się dalej. Dopasowuje swoje argumenty poprzez kolor ucieczki koloru i nie obsługuje ich, dopóki nie jest zdecydowanie gotowy do wydrukowania linii. Wszystko to jest dla mnie bardzo trudne do zrobienia z większą ilością danych niż pojedyncza linia na raz.
mikeserv

1

Każda powłoka ma swój własny zestaw wbudowanych funkcji. Chociaż istnieją podobieństwa, każda z nich ma swoje osobliwości, które należy udokumentować.

W systemach takich jak Linux i FreeBSD (i OSX, który dziedziczy po FreeBSD), gdzie każda powłoka jest dostarczana jako osobny pakiet, nie ma strony podręcznika dla wbudowanych; zamiast tego każde wbudowane jest udokumentowane na stronie man powłoki. Przeczytaj więc stronę podręcznika użytkownika bash, aby uzyskać dokumentację killwbudowanego narzędzia bash , przeczytaj stronę podręcznika dash, aby uzyskać dokumentację killwbudowanego narzędzia dash itp. Istnieje również strona podręcznika dla killsamodzielnego narzędzia.

Zobacz: Czy mogę uzyskać pojedyncze strony podręcznika dla wbudowanych poleceń bash? dla manfunkcji, która pokazuje wewnętrzną dokumentację bash zamiast strony man, jeśli argument jest nazwą wbudowanego.

Istnieją warianty unixowe, które zapewniają strony podręcznika dla wbudowanych powłok - w rzeczywistości większość wariantów komercyjnych to robi. Jest to wykonalne, ponieważ system jest wyposażony w pojedynczą powłokę lub zestaw znanych powłok. Strona podręcznika omawia różnice między powłokami. Na przykład, fg(1)strona człowiek na Solaris 10 ma sekcje sh, kshi csh. fg(1)Strona człowiek na AIX 7.1 odniesień „Korn shell” i „POSIX Shell”, ale omawia je ze sobą (zdarzają się wspierać dokładnie te same funkcje fg). fg(1)Strona człowiek na Tru64 5,0 omawia wbudowane ksh i csh odsyła użytkowników do csh(1)strony człowieka. SCOnajwyraźniej ma jedną powłokę. Możesz zainstalować inne powłoki jako pakiety dodatkowe w tych systemach operacyjnych; jeśli używasz niestandardowej powłoki, musisz pamiętać, że strony podręcznika dla wbudowanych poleceń nie będą odpowiednie, gdy używasz powłoki innej niż domyślna.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.