쉘 내장에 적절한 매뉴얼 페이지가없는 이유는 무엇입니까?


32

모든 쉘 내장은 동일한 매뉴얼 페이지를 공유합니다.

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

NAME
     builtin, !

기타

그런 다음 쉘 내장이 무엇인지 설명하고 다음과 같은 목록을 보여주는 작은 텍스트가 있습니다.

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

그러나 우리가하면 우리는 man grep같은 섹션을 얻을

  • 버그
  • 역사
  • 참조
  • 표준
  • 기술

기타

내장 명령과 같은 자신의 역사, 설명 및 인수가 쉘하지 마십시오 -A또는 -r? 매뉴얼 페이지에 제공되지 않는 이유는 무엇이며 올 바르고 효율적으로 사용하는 방법을 배우려면 어떻게해야합니까?


답변:


25

내장은 쉘의 일부이기 때문입니다. 버그 나 이력은 쉘 자체의 버그와 이력입니다. 이들은 독립적 인 명령이 아니며 내장 된 쉘 외부에는 존재하지 않습니다.

bash적어도 그에 상응하는 것은 help명령입니다. 예를 들면 다음과 같습니다.

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

모든 배쉬 내장에는 help페이지가 있습니다. 심지어 help자체를 :

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

@mikeserv의 sed스크립트에서 영감을 얻은 다음은 Perl을 사용하여 매뉴얼 페이지의 관련 섹션을 인쇄하는 작은 기능입니다. 이 줄을 쉘의 초기화 파일에 추가하십시오 ( ~/.bashrcbash의 경우).

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

그런 다음 맨 페이지와 섹션 이름을 지정하여 실행합니다.

$ 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 있습니다 배쉬. 그것들은 그것의 일부이며 예, 매뉴얼 페이지 의 SHELL BUILTIN COMMANDS섹션 에서 설명됩니다 bash. 그들의 "맨 페이지"는 help builtin_name입니다.
terdon

3
분명하지 않은 것은 매뉴얼 페이지가 제공되지 않은 이유입니다. 매뉴얼 페이지는 MANPATH의 파일 일뿐입니다. 별도의 바이너리에 해당하지 않아도됩니다. bash가 내부 도움말 시스템이 아닌 내장 페이지의 매뉴얼 페이지를 제공하지 못한 이유는 원칙적으로 없습니다.
Francis Davey

4
@FrancisDavey : 그러나 대부분의 내장은 다양한 쉘에 (다른 확장자로) 존재합니다. 맨 페이지는 셸별로 다릅니다. 그들은 시스템 전체입니다.
rici

2
@FrancisDavey rici가 말했듯이, 명령은 시스템 전체가 아닙니다. 그것은 조금 모든 쉘에 존재하지 않는, 그러나 더 나쁜, 아주 명령에 대한 man 페이지가 혼동 할 것이다 명령에 대한 맨 페이지를 가지고 오해의 소지가 될 것 입니다 다수의 껍질에 존재하는, 그러나 어떤이 다르게 동작 (예를 들어, , 다른 인수를 허용하고 구문이 다릅니다.)
Joshua Taylor

1
@mikeserv 그러나, 나는 곳이 무엇을, 예를 들어, 자식 이벤트의 라인을 따라 쉘 내장 명령에 대한 매뉴얼 페이지 환영 man git commit에 대한 man 페이지를 불러옵니다 git-commit. 같은 뭔가 man bash if가 될 것입니다 멋진 .
Joshua Taylor

5

일부 쉘 내장 명령이 부족한 완전한 매뉴얼에 표시 가질 수 있다는 것이 사실이지만 - 특히 사람들을 위해 bash당신이 GNU 시스템에서 사용하기 만 가능성이 있음 - 특정 내장 명령 을 믿지 않는, 원칙적으로 (는 GNU 사람들, man그리고 자신의 선호 info) 페이지 - 그렇지 않으면 쉘 내장 명령 또는 - - POSIX 유틸리티의 대부분은 아주 잘 POSIX 프로그래머 가이드에 표시됩니다.

여기 내 바닥에서 발췌 한 것입니다 man sh (아마 20 페이지 정도일 수 있습니다 ...)

여기에 이미지 설명을 입력하십시오

그 모든이 있고, 다른 사람은 언급하지 않은 set, read, break... 음, 내가 그들 모두 이름을 할 필요가 없습니다. 그러나 (1P)오른쪽 하단에-POSIX 카테고리 1 매뉴얼 시리즈를 나타냅니다-그것들은 man내가 말하고 있는 페이지입니다.

패키지를 설치해야 할 수도 있습니다. 이것은 데비안 시스템에 유망한 것으로 보입니다. help유용 하지만 찾을 수 있으면 분명히 해당 POSIX Programmer's Guide시리즈 를 가져와야합니다. 매우 도움이 될 수 있습니다. 그리고 구성 페이지는 매우 상세합니다.

그 외에도 쉘 내장은 거의 항상 특정 쉘 매뉴얼의 특정 섹션에 나열되어 있습니다. zsh예를 들어, 그에man 대한 별도의 전체 페이지가 있습니다 (총 8 또는 9 정도의 개별 zsh페이지가 있다고 생각합니다 zshall.

당신 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

... 쉘 man페이지를 검색 할 때 사용한 것과 매우 비슷 합니다. 그러나 대부분의 경우에 help아주 좋습니다 bash.

실제로 sed최근에 이런 종류의 물건을 처리하기 위해 스크립트를 작성하고 있습니다. 위의 그림에서 섹션을 잡은 방법입니다. 여전히 내가 좋아하는 것보다 더 길지만 개선되고 있으며 꽤 유용 할 수 있습니다. 현재 반복에서는 명령 행에 주어진 [a] 패턴을 기반으로 섹션 또는 하위 섹션 제목과 일치하는 상황에 맞는 텍스트 섹션을 상당히 안정적으로 추출합니다. 출력을 채색하고 표준 출력으로 인쇄합니다.

들여 쓰기 수준을 평가하여 작동합니다. 비 공백 입력 라인은 일반적으로 무시되지만 빈 라인이 발견되면주의를 기울이기 시작합니다. 다른 빈 줄이 발생하기 전에 첫 번째 줄보다 현재 시퀀스가 ​​확실히 더 들여 쓰기되는지 확인할 때까지 거기에서 줄을 수집합니다. 그렇지 않으면 스레드를 삭제하고 다음 빈을 기다립니다. 테스트가 성공하면 명령 줄 인수와 리드선을 일치 시키려고 시도합니다.

이는 일치 패턴이 다음과 일치 함을 의미합니다 .

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

..과..

match
   text

..하지만..

heading
    match
    match

    notmatch

..또는..

         text

         match
         match
         text

         more text

일치하는 것이 있으면 인쇄를 시작합니다. 인쇄 된 모든 줄에서 일치하는 줄의 선행 공백을 제거합니다. 따라서 들여 쓰기 수준에 상관없이 해당 줄이 맨 위에있는 것처럼 인쇄합니다. 일치하는 줄과 같거나 적은 들여 쓰기 수준에서 다른 줄이 나타날 때까지 계속 인쇄되므로 전체 섹션에는 포함 된 단락의 일부 / 모든 하위 섹션을 포함하여 제목이 일치합니다.

따라서 기본적으로 패턴과 일치하도록 요청하면 특정 제목의 제목에만 적용되며 일치하는 섹션에서 찾은 모든 텍스트를 색칠하고 인쇄합니다. 첫 번째 줄의 들여 쓰기를 제외 하고는이 작업을 수행 할 때 아무것도 저장되지 않으므로 매우 빠르며 \n거의 모든 크기의 ewline으로 구분 된 입력을 처리 할 수 ​​있습니다 .

다음과 같은 소제목으로 재귀하는 방법을 알아내는 데 잠시 시간이 걸렸습니다.

Section Heading
    Subsection Heading

그러나 결국 그것을 정리했습니다.

그러나 단순화를 위해 모든 것을 재 작업해야했습니다. 이전에는 여러 작은 루프가 컨텍스트에 맞게 약간 다른 방식으로 거의 동일한 방식으로 작업을 수행하는 동안 재귀 방법을 변경하여 코드의 대부분을 중복 제거했습니다. 이제 두 개의 루프가 있습니다-하나는 인쇄물과 하나는 들여 쓰기입니다. 둘 다 동일한 테스트에 의존합니다. 테스트가 통과하면 인쇄 루프가 시작되고 실패하거나 빈 줄에서 시작하면 들여 쓰기 루프가 대신됩니다.

전체 프로세스는 매우 빠르기 때문에 대부분의 경우 /./d빈 줄이 아닌 행을 생략하고 다음 줄로 넘어갑니다 zshall. 화면을 즉시 채우는 결과도 있습니다 . 변경되지 않았습니다.

어쨌든 지금까지는 매우 유용합니다. 예를 들어 read위의 작업은 다음과 같이 수행 할 수 있습니다.

mansed bash read

... 그리고 전체 블록을 얻습니다. 첫 번째는 항상 man검색해야하는 페이지 이지만 모든 패턴이나 무엇이든 또는 여러 인수를 취할 수 있습니다 . 다음은 내가 한 후의 결과 중 일부 그림입니다 .

mansed bash read printf

여기에 이미지 설명을 입력하십시오

... 두 블록 모두가 반환됩니다. 나는 종종 그것을 다음과 같이 사용합니다 :

mansed ksh '[Cc]ommand.*'

... 매우 유용합니다. 또한 얻는 SYNOPS[ES]것이 정말 편리합니다.

여기에 이미지 설명을 입력하십시오

여기에 소용돌이를 주길 원한다면-당신이하지 않으면 나는 당신을 비난하지 않을 것입니다.

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

간단히 말해 워크 플로는 다음과 같습니다.

  • 공백이 아니고 \newline 문자를 포함하지 않는 행 은 출력에서 ​​삭제됩니다.
    • \n입력 패턴 공간에서 ewline 문자는 절대 발생하지 않습니다. 편집 결과로만 가질 수 있습니다.
  • :print:indent모두 상호 의존적 폐쇄 루프이며 얻는 유일한 방법 \newline한다.
    • :print행의 선행 문자가 일련의 공백 다음에 \newline 문자 인 경우 루프 순환이 시작됩니다 .
    • :indent사이클은 빈 라인에서 시작하거나 :print실패한 사이클 라인 에서 시작 #test하지만 출력에서 :indent모든 선행 공백 + \newline 시퀀스를 제거합니다 .
    • 일단 :print시작하면 입력 라인을 계속 끌어오고, 사이클의 첫 번째 라인에서 찾은 양만큼 선행 공백을 제거하고 오버 스트라이크 및 언더 스트라이크 백 스페이스 이스케이프를 컬러 터미널 이스케이프로 변환 한 다음 #test실패 할 때까지 결과를 인쇄 합니다.
    • :indent시작 하기 전에 먼저 h가능한 빈 공간이 있는지 (예 : 하위 섹션) 오래된 공간을 확인한 다음 #test실패하고 첫 번째 줄 뒤의 행이 계속 일치하는 한 계속 입력을 가져옵니다 [-. 첫 번째 줄 이후의 줄이 해당 패턴과 일치하지 않으면 삭제되고 다음 빈 줄까지 다음 줄도 모두 삭제됩니다.
  • #match그리고 #test두 개의 폐쇄 루프를 해소.
    • #test행의 선행 공백이 \n행 순서에서 마지막 ewline 다음에 오는 시리즈보다 짧을 때 통과 합니다.
    • #match모든 명령 행 arg와 일치하는 출력 시퀀스 중 하나에 \n대한 :print주기 를 시작하는 데 필요한 선행 ewlines를 추가합니다 :indent. 비어 있지 않은 시퀀스는 빈 행으로 표시되고 결과 빈 줄은로 다시 전달됩니다 :indent.

2
당신의 sed-fu는 강하다. 물론, 당신과 같은 일을 할 수있는 manperl(){ man $1 | perl -00ne "print if /^\s*$2\b/"; }다음과 manperl sh SYNOPSISmanperl sh read:
terdon

@ terdon-아니, 당신은 할 수 없습니다. 이것은 입력을 먹지 않습니다. 나는 sed 'H;$!d;g;s/\(\(\n *\)match\([^\n]*\)\2 \)\{1,\}\)*.\{,1\}/\1/g'아마도 ... 작동 하는 것과 같은 일을 할 수는 있지만 파일을 삼키고 한 번에 파싱해야합니다. 이것은 스트림에서 작동합니다-라인이 천문학적으로 길지 않은 경우 모든 크기의 입력을 처리 할 수 ​​있습니다. 그것은 작품으로는 인쇄 - 그것은 모든 구문 분석 man\backslash 탈출에 시동을. 그러나 man그것은 단지 하나의 응용 프로그램입니다 – 나는 다른 문제들에도 많이 적용했습니다…
mikeserv

1
작은 라이너로 설명 할 수 있기 때문에 체인을 잡아 당기고 있습니다. 그러나 파일 전체를 삼키지 않고 스트림에서 작동합니다. 그것은 \n\n대신 "줄"을 정의 \n하지만 여전히 모든 크기의 입력과 인쇄를 처리 할 수 ​​있습니다. 여기에서 "문단 모드"를 참조하십시오 : perldoc.perl.org/perlrun.html
terdon

@terdon 어쩌면 여기에 더 나은 방법 일 것입니다. 다음 sed과 같이 할 수 있습니다 : '/./{H;$!d' -e '};x;now work the paragraph...'. 나는 종종 그렇게한다. 그러나 나는 원래 로그 라이브를 무제한으로 보는 첫 번째 부분을 썼으며 심지어 그 행동조차도 가능했습니다. 버퍼는 특정 조건에서 폭발 할 수 있습니다. 그것은이 크기의 절반 밖에되지 않았습니다 man. 나는 위 man -Hman시놉시스를 얻은 후에 살펴 보았고 groff가 GNU 시스템에서 인쇄 할 수있는 기계 생성 HTML로 작업하는 것이 더 쉬울 것이라고 생각합니다. 나는 이미 팔꿈치가 깊다
mikeserv

@ terdon-나는 나 자신을 두 번째로 추측하고 단락 중심의 접근법을 시도하지만, 더 쉽습니다. 이것은 섹션을 가져옵니다. 마찬가지로 mansed cmd DESCRIPTIONDESCRIPTION 섹션을 가져옵니다-포함 된 모든 섹션. 일치하는 검색은 전체와 들여 쓰기 수준이 최상위 수준 인 것처럼 인쇄됩니다. 심지어 일치하지만 더 이상 들여 쓰지 않는 단락을 무시하여 오 탐지를 건너 뜁니다. 색상 백 스페이스 이스케이프를 통해 인수와 일치 하며 라인을 인쇄 할 준비가 될 때까지 처리하지 않습니다. 이 모든 것이 한 번에 한 줄보다 훨씬 많은 데이터로 처리하기가 매우 어렵습니다.
mikeserv

1

각 쉘에는 자체 내장 세트가 있습니다. 공통점이 있지만 각각 문서화해야 할 고유 한 특성이 있습니다.

각 쉘이 별도의 패키지로 제공되는 Linux 및 FreeBSD (및 FreeBSD에서 상속되는 OSX)와 같은 시스템에는 내장 매뉴얼 페이지가 없습니다. 대신, 각 내장은 쉘의 매뉴얼 페이지에 문서화되어 있습니다. 따라서 bash의 kill내장 에 대한 문서는 bash 매뉴얼 페이지를 읽고 대시의 kill내장 에 대한 문서는 대시 매뉴얼 페이지를 읽으십시오 kill. 독립형 유틸리티에 대한 매뉴얼 페이지도 있습니다 .

bash 내장 명령에 대한 개별 매뉴얼 페이지를 얻을 수 있습니까?를 참조하십시오 . man인수가 내장의 이름 인 경우 매뉴얼 페이지 대신 bash의 내부 문서를 표시 하는 함수

쉘 내장에 대한 매뉴얼 페이지를 제공하는 유닉스 변형이 있습니다. 실제로 대부분의 상용 변형이 있습니다. 시스템에는 단일 셸 또는 알려진 셸 세트가 제공되므로 가능합니다. 매뉴얼 페이지는 쉘 간의 차이점에 대해 설명합니다. 예를 들어, fg(1)Solaris 10의 매뉴얼 페이지 에 대한 섹션이 있습니다 sh, ksh하고 csh. fg(1)AIX 7.1매뉴얼 페이지는 “Korn shell”및“POSIX shell”을 참조하지만 함께 논의합니다 (에 대해 정확히 동일한 기능을 지원함 fg). fg(1)Tru64 5.0매뉴얼 페이지 는 ksh 내장에 대해 설명하고 csh 사용자를 csh(1)매뉴얼 페이지로 참조합니다. SCO분명히 단일 쉘이 제공됩니다. 이러한 운영 체제에서 다른 쉘을 애드온 패키지로 설치할 수 있습니다. 사용자 정의 쉘을 사용하는 경우 기본이 아닌 쉘을 사용할 때 내장의 매뉴얼 페이지는 관련이 없음을 기억해야합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.