macOSでマニュアルページを検索しようとすると、奇妙な動作が発生します。たとえば、Bash のマニュアルページには次の文字列が目立つように表示されますNAME
。
$ man bash | head -5 | tail -1
NAME
grepを実行するとname
結果が得られますが、grepを実行すると結果はNAME
得られません。
$ man bash | grep 'NAME'
$ man bash | grep NAME
私が知っている他の大文字の単語を試してみましたが、検索SHELL
結果が出ませんでしたBASH
。
ここで何が起こっているのでしょうか?
修正する:すべての回答ありがとうございます!この問題が発生した理由の背景を追加する価値があると思いました。私はWrapのbash関数を書くのが好きでman
、シェル組み込み関数のマニュアルページを見つけようとすると、Bashのマニュアルページの関連セクションに移動します。おそらくより良い方法があります。しかし、現在私が持っている方法は次のとおりです。
man () {
case "$(type -t "$1")" in
builtin)
local pattern="^ *$1"
if bashdoc_match "$pattern \+[-[]"; then
command man bash | less --pattern="$pattern +[-[]"
elif bashdoc_match "$pattern\b"; then
command man bash | less --pattern="$pattern[[:>:]]"
else
command man bash
fi
;;
keyword)
command man bash | less --hilite-search --pattern='^SHELL GRAMMAR$'
;;
*)
command man "$@"
;;
esac
}
bashdoc_match() {
command man bash | col -b | grep -l "$1" > /dev/null
}
答え1
印刷できない文字を表示するためにコマンド| sed -n l
にaを追加すると、次の内容が表示されることがあります。tail
N\bNA\bAM\bME\bE
つまり、各文字はX
Backspaceで作成されますX
。最新の端末では文字自体を上書きするので(バックスペース(BSとも呼ばれる)はカーソルを1列左に移動する文字なので\b
)何の違いもありません。^H
しかし、古代テレタイプではインクの量が2倍なので、文字が太字で表示されます。
それにもかかわらず、more
/のようなポケットベルはフォーマットless
が太字で表示されることを理解しているので、これはまだroff
太字のテキストを出力する方法です。
一部の実装では、roff
これらのシーケンスを使用しない方法でそれを呼び出す(または実装のようにそれをcol -b -p -x
削除するために内部的に呼び出されますman-db
(MAN_KEEP_FORMATTING
環境変数が設定されていない場合))、出力が次の場合にページャを呼び出さない。検出されて端末に移動しませんが(そこでman bash | grep NAME
作業しても大丈夫です)、端末には移動しません。
を使用して、これらのシーケンス(他のタイプ(BS)とアンダースコアもcol -b
あります)を削除できます。_
X
GNU(GNUやFreeBSDなど)を使用するシステムでは、roff
オプションがに渡されることを確認して最初からこれらのシーケンスを使用しないことがあります。-c -b -u
grotty
-P-cbu
groff
groff
たとえば、「include」というラッパースクリプトを作成すると、次のようになります。
#! /bin/sh -
exec /usr/bin/groff -P-cbu "$@"
/usr/bin/groffの前に置きます$PATH
。
macOS man
(GNUを使用roff
)を使用すると、man-no-overstrike.conf
次のように作成できます。
NROFF /usr/bin/groff -mandoc -Tutf8 -P-cbu
次のように呼び出されますman
。
man -C man-no-overstrike.conf bash | grep NAME
それでもGNUを使用してroff
環境変数を設定した場合(またはコンパイル時のデフォルト設定方法に従って変数を設定しない限りGROFF_SGR
)(オプションが渡されない限り)、ANSI SGR端末エスケープシーケンスが使用されます。 。役割属性のナンセンスです。オプションを呼び出すときはこれを理解してください。GROFF_NO_SGR
grotty
-c
less
-R
FreeBSDの人はあなたが要求しない限りgrotty
このオプションを呼び出すでしょう-c
色MANCOLOR変数を設定します(この場合、ANSI SGRエスケープシーケンスを使用して渡さ-c
れず、grotty
デフォルト値grotty
に戻ります)。
MANCOLOR=1 man bash | grep NAME
そこで働きます。
Debian では、GROFF_SGR はデフォルト値ではありません。これにより:
GROFF_SGR=1 man bash | grep NAME
しかしman
、のstdoutは端末ではなく、それ自体が変数を渡すGROFF_NO_SGR
ので(まだ実行していてもSGRシーケンスを削除する方法がわからないため、BSシーケンスを削除するgrotty
ために使用できるようです)上書きされます。私たちの。col -bpx
col
MAN_KEEP_FORMATTING
GROFF_SGR
GROFF_SGR=1 MANPAGER='grep NAME' man bash
(端末から)SGRエスケープシーケンスを取得します。
その時点で、次のいくつかが見つかります。名前sは端末(およびポケットベル)に太字で表示されますless -R
。出力をsed -n l
()に入力すると、MANPAGER='sed -n /NAME/l'
次の内容が表示されます。
\033[1mNAME\033[0m$
その中には、\e[1m
ANSI互換端末で太字のフォントを有効にするシーケンスと、\e[0m
すべてのSGR属性をデフォルト値に復元するシーケンスがあります。
これがgrep NAME
機能する方法は、テキストにその内容が含まれていることですNAME
。ただし、テキストの一部だけが太字/下線付きのテキストを見つけると、問題が発生する可能性があります。
答え2
マンページを見ると、タイトルが太字で表示されていることがわかります。これは、制御文字を使用して書式を設定することによって行われます。あなたが望むものを好きにするには、grep
それらを削除する必要があります。
このcol
ユーティリティは、次の目的で使用できます。
$ man bash | col -b | grep 'NAME'
この-b
オプションには次の説明があります。OpenBSDから:
バックスペースは出力されず、各列位置に書き込まれた最後の文字のみが印刷されます。これはmandoc(1)の出力を処理するのに役立ちます。
Linuxcol
マニュアル(Ubuntu)には最後の文章はありません(しかし同じように動作します)。
Linuxでは、環境変数の設定を解除したり空の文字列に設定したりすることも役立ちます。出力をMAN_KEEP_FORMATTING
渡す必要はありません。grep
man
col -b