シェルビルトインに適切なマニュアルページがないのはなぜですか?


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.

すべてのbashビルトインには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を使用してmanページの関連セクションを印刷する小さな関数があります。この行をシェルの初期化ファイルに追加します(~/.bashrcbashの場合):

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

次に、manページとセクション名を指定して実行します。

$ 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 bashです。それらはその一部であり、はい、マニュアルページのSHELL BUILTIN COMMANDSセクションで説明されていbashます。それらの「マニュアルページ」はhelp builtin_nameです。
テルドン

3
明確ではないのは、それらがマニュアルページを与えられなかった理由です。マニュアルページは、MANPATH上の単なるファイルです。それらは別々のバイナリに対応する必要はありません。原則として、bashがビルトインのマニュアルページを同梱できなかった理由はありません-内部ヘルプシステムがあるのではありません。
フランシスデイビー14年

4
@FrancisDavey:ただし、ほとんどのビルトインは(さまざまな拡張子を持つ)さまざまなシェルに存在します。マンページはシェル固有ではありません。それらはシステム全体です。
リチ14年

2
@FrancisDavey riciが言ったように、コマンドはシステム全体ではありません。これは、すべてのシェルに存在しないコマンドのマンページを持つことが誤解を招くビットが、さらに悪い、非常にコマンドのmanページを持つことが混乱するだろうだろうある複数のシェルに存在するが、異なる動作をしている(たとえば、 、異なる引数を受け入れ、異なる構文を持ちます。など)。
ジョシュアテイラー14年

1
@mikeservしかし、私は考えところ何、例えば、gitの提供、の線に沿ってシェル組み込みコマンドのmanページを歓迎man git commitするためにmanページが表示されますgit-commit素晴らしいものがあるman bash ifでしょう。
ジョシュアテイラー14年

5

いくつかのシェル組み込みコマンドは乏しいが、完全なマニュアルに示す有してもよいことが、それは本当だが-特にそれらのためにbashあなたがGNUシステム上での使用のみになりそうだという固有の組み込みコマンドを信じていない、原則として(GNUの人々 、manおよび独自のinfoページを好みます) -POSIXユーティリティの大部分-シェル組み込みまたはその他-POSIX Programmer's Guideに非常によく表されています。

これは私の下部からの抜粋ですman sh (おそらく20ページほどか...)

ここに画像の説明を入力してください

それらのすべてがそこにあり、他はそのような言及していないsetreadbreak...よく、私はそれらすべてに名前を付ける必要はありません。しかし(1P)、右下にあることに注意してください-それはPOSIXカテゴリ1マニュアルシリーズを示しています-それらはman私が話しているページです。

パッケージをインストールするだけでいいのでしょうか?これはDebianシステムにとって有望に見えます。一方でhelp便利です、あなたはそれを見つけることができれば、あなたは間違いなくそれを取得する必要POSIX Programmer's Guideシリーズを。これは非常に役立ちます。また、構成ページは非常に詳細です。

それを除けば、シェルの組み込みコマンドはほとんどの場合、特定のシェルのマニュアルの特定のセクションにリストされています。zsh、たとえば、manそのための完全な個別のページがあります- (私はそれが巨大であるものzshを含めzshallて8または9かそこらの個々のページで合計すると思います)

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、実質的に任意のサイズの改行で区切られた入力を処理できます。

次のような小見出しに再帰する方法を見つけるのにしばらく時間がかかりました。

Section Heading
    Subsection Heading

しかし、最終的に整理しました。

ただし、単純にするためにすべてをやり直す必要がありました。いくつかの小さなループがコンテキストを合わせるためにわずかに異なる方法でほとんど同じことを行う前に、再帰の手段を変えることで、コードの大部分を重複排除することができました。現在、2つのループがあります。1つは印刷で、もう1つはインデントをチェックします。両方とも同じテストに依存します。テストに合格すると印刷ループが開始され、失敗または空白行でインデントループが引き継がれます。

プロセス全体は非常に高速です。ほとんどの場合、/./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
");}

簡単に言うと、ワークフローは次のとおりです。

  • 空白ではなく、\n改行文字を含まない行は出力から削除されます。
    • \n入力パターンスペースにewline文字が含まれることはありません。それらは編集の結果としてのみ持つことができます。
  • :print:indentは、相互に依存する閉ループであり、\newline を取得する唯一の方法です。
    • :printのループサイクルは、行の先頭の文字が一連の空白で、その後に\n改行文字が続く場合に始まります。
    • :indentのサイクルは空白行で開始します-または、:print失敗したサイクル行で開始します#testが、出力から:indentすべての先行ブランク+ \newlineシーケンスを削除します。
    • 一度:print、入力ラインにプルしていきますから始まり、量に空白を至るまでのストリップが重ね打ち翻訳し、そのサイクルの最初の行で見つかったとunderstrikeバックスペースエスケープカラーの端末エスケープに、とまでは結果を印刷#testに失敗します。
    • :indent開始する前に、hインデントの継続 Subsection など)がないか古いスペースを最初にチェックし、#test失敗し、最初の行に続く行が一致し続ける限り、入力を引き込み続け[-ます。最初の行より後の行がそのパターンに一致しない場合は削除されます。その後、次の行も次の空白行まで削除されます。
  • #matchそして#test2つの閉ループを橋渡しします。
    • #test空白の先頭のシリーズが\n、行シーケンスの最後のewlineが続くシリーズよりも短い場合に通過します。
    • #matchは、コマンドライン引数との一致を伴う出力シーケンスのいずれかにサイクル\nを開始するために必要な先頭のewlinesを追加します。表示されないシーケンスは空になり、結果の空白行がに返されます。:print:indent:indent

2
あなたのセドフは強いです。もちろん、同じことをしてmanperl(){ man $1 | perl -00ne "print if /^\s*$2\b/"; }から、manperl sh SYNOPSISまたはmanperl sh read:)
terdon

@terdon-いいえ、できません。これは入力を食べません。私はsed 'H;$!d;g;s/\(\(\n *\)match\([^\n]*\)\2 \)\{1,\}\)*.\{,1\}/\1/g'...おそらく同じように...おそらくそれが機能するのと同じことをすることができますが、ファイルを飲み込んで一度に解析する必要があります。これはストリームで機能します-行が天文学的に長くない限り、任意のサイズの入力を処理できます。動作するように出力します-そして、すべてmanのの\bスラッシュエスケープを解析して起動します。しかしman...私は、他の問題のために、それの多くを適用した-それのために1つだけのアプリケーションです
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を使用する方が簡単かもしれないと考えています。私はthougすでにちょっと肘深いんだ
mikeserv

@terdon-私は自分でセカンド推測を行い、段落中心のアプローチを試みましたが、それはそのままの方が簡単です。これはセクションを取得します。Like mansed cmd DESCRIPTIONはDESCRIPTIONセクションを取得し、含まれているすべてのセクションを取得します。一致した検索は、インデントレベルがトップレベルであるかのように全体が印刷されます。一致するがその後インデントしない段落を無視することで、誤検知をスキップします。色のバックスペースエスケープを通じて引数と一致し、行を印刷する準備が確実に整うまで、それらを処理しません。一度に1行よりもはるかに多くのデータを処理することは、私にとって非常に困難です。
mikeserv 14年

1

各シェルには、独自の組み込みセットがあります。共通点はありますが、それぞれ独自の特性があり、文書化する必要があります。

LinuxやFreeBSD(およびFreeBSDを継承するOSX)などのシステムでは、各シェルが個別のパッケージとして提供されており、組み込みのマニュアルページはありません。代わりに、各ビルトインはシェルのマニュアルページに記載されています。そのため、bashのkill組み込みのドキュメントについてはbashのマニュアルページを、ダッシュのkill組み込みのドキュメントについてはダッシュのmanページを読んでくださいkill。スタンドアロンユーティリティのマニュアルページもあります。

bash組み込みコマンドの個別のマニュアルページを取得できますか?を参照してくださいman引数が組み込みの名前である場合、manページの代わりにbashの内部ドキュメントを表示する関数の場合。

シェルビルトインのマニュアルページを提供するUNIXバリアントがあります。実際、ほとんどの商用バリアントが提供しています。システムには単一のシェルまたは既知のシェルのセットが付属しているため、これは実現可能です。マニュアルページでは、シェルの違いについて説明しています。たとえば、fg(1)Solaris 10のマニュアルページにshkshおよびのセクションがありcshます。fg(1)AIX 7.1マニュアルページでは、「Kornシェル」と「POSIXシェル」が参照されていますが、それらについては一緒に説明されています(これらはまったく同じ機能をサポートしていますfgfg(1)Tru64 5.0マニュアルページでは、kshビルトインについて説明し、cshユーザーにcsh(1)マニュアルページを紹介しています。SCO明らかに単一のシェルが付属しています。これらのオペレーティングシステムには、他のシェルをアドオンパッケージとしてインストールできます。カスタムシェルを使用する場合、デフォルト以外のシェルを使用する場合、ビルトインのマニュアルページは関係がないことに注意する必要があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.