Je rencontre un comportement étrange en essayant de grep une page de manuel sur macOS. Par exemple, la page de manuel Bash a clairement une occurrence de la chaîne NAME
:
$ man bash | head -5 | tail -1
NAME
Et si je convoite, name
j'obtiens des résultats, mais si je convoite, NAME
je ne le fais pas:
$ man bash | grep 'NAME'
$ man bash | grep NAME
J'ai essayé d'autres mots en majuscules que je sais être là, et la recherche de SHELL
rendements ne donne rien alors que la recherche de BASH
résultats donne.
Que se passe t-il ici?
Mise à jour : Merci pour toutes les réponses! J'ai pensé qu'il valait la peine d'ajouter le contexte dans lequel je me suis heurté à cela. Je voulais écrire une fonction bash pour envelopper man
et dans les cas où j'ai essayé de rechercher la page de manuel pour un shell intégré, passez à la section appropriée de la page de manuel Bash. Il pourrait y avoir une meilleure façon, mais voici ce que j'ai actuellement:
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
}
man bash | grep NAME
fonctionne comme prévu.help
commande bash pour obtenir ses informations.help
résultats en oublient trop. Vérifiezhelp complete
contre lacomplete
section dansman bash
, par exemple.Réponses:
Si vous ajoutez un
| sed -n l
à cettetail
commande, pour afficher des caractères non imprimables, vous verrez probablement quelque chose comme:Autrement dit, chaque caractère est écrit comme
X
BackspaceX
. Sur les terminaux modernes, le personnage finit par être écrit sur lui-même (comme Backspace aka BS aka\b
aka^H
est le personnage qui déplace le curseur d'une colonne vers la gauche) sans différence. Mais dans les anciennes machines à écrire, cela ferait apparaître le caractère en gras car il obtient deux fois plus d'encre.Pourtant, les pagers aiment
more
/less
comprennent ce format comme signifiant gras, c'est donc ce quiroff
fait pour produire du texte en gras.Certaines implémentations man appellent
roff
de manière à ce que ces séquences ne soient pas utilisées (ou appellent en internecol -b -p -x
pour les supprimer comme dans le cas de l'man-db
implémentation (à moins que laMAN_KEEP_FORMATTING
variable d'environnement ne soit définie)), et n'invoquent pas de pager lorsqu'elles détectent la sortie ne va pas à un terminal (doncman bash | grep NAME
fonctionnerait là-bas), mais pas le vôtre.Vous pouvez utiliser
col -b
pour supprimer ces séquences (il existe également d'autres types (_
BSX
) pour souligner).Pour les systèmes utilisant GNU
roff
(comme GNU ou FreeBSD), vous pouvez éviter que ces séquences soient utilisées en premier lieu en vous assurant que les-c -b -u
options sont passées àgrotty
, par exemple en vous assurant que les-P-cbu
options sont passées àgroff
.Par exemple en créant un script wrapper appelé
groff
contenant:Que vous placez devant / usr / bin / groff
$PATH
.Avec macOS '
man
(utilisant également GNUroff
), vous pouvez créer unman-no-overstrike.conf
avec:Et appelez
man
comme:Toujours avec GNU
roff
, si vous définissez laGROFF_SGR
variable d'environnement (ou si vous ne définissez pas laGROFF_NO_SGR
variable en fonction de la façon dont les valeurs par défaut ont été définies au moment de la compilation), alorsgrotty
(tant qu'elle n'est pas transmise, l'-c
option) utilisera des séquences d'échappement du terminal ANSI SGR à la place. de ces astuces BS pour les attributs de personnage.less
les comprendre lorsqu'ils sont appelés avec l'-R
option.L'homme de FreeBSD appelle
grotty
avec l'-c
option à moins que vous ne demandiez des couleurs en définissant la variable MANCOLOR (auquel cas il-c
n'est pas passé àgrotty
etgrotty
revient à la valeur par défaut de l'utilisation des séquences d'échappement ANSI SGR là-bas).fonctionnera là-bas.
Sur Debian, GROFF_SGR n'est pas la valeur par défaut. Si tu fais:
cependant, parce que
man
stdout n'est pas un terminal, il prend sur lui de passer également uneGROFF_NO_SGR
variable àgrotty
(je suppose donc qu'il peut utilisercol -bpx
pour supprimer les séquences BS carcol
il ne sait pas comment supprimer les séquences SGR, même s'il reste le fait avecMAN_KEEP_FORMATTING
) qui l'emporte sur notreGROFF_SGR
. Vous pouvez faire à la place:(dans un terminal) pour avoir les séquences d'échappement SGR.
Cette fois, vous remarquerez que certains de ces NOM apparaissent en gras sur le terminal (et dans un
less -R
pager). Si vous alimentez la sortie ensed -n l
(MANPAGER='sed -n /NAME/l'
), vous verrez quelque chose comme:Où
\e[1m
est la séquence pour activer le gras dans les terminaux compatibles ANSI, et\e[0m
la séquence pour rétablir tous les attributs SGR par défaut.Sur ce texte
grep NAME
fonctionne comme ce texte contientNAME
, mais vous pouvez toujours avoir des problèmes si vous recherchez du texte dont seules certaines parties sont en gras / souligné ...la source
sed -n l
tant que substitutod
.Si vous consultez une page de manuel, vous remarquerez que les en-têtes sont en gras. Ceci est réalisé en les formatant avec des caractères de contrôle. Pour pouvoir
grep
aimer ce que vous voulez, ceux-ci doivent être supprimés.L'
col
utilitaire peut être utilisé pour cela:L'
-b
option a la description suivante sur OpenBSD :Linux le
col
manuel (sur Ubuntu) ne contient pas la dernière phrase (mais il fonctionne de la même manière).Sous Linux, la suppression de la
MAN_KEEP_FORMATTING
variable d'environnement (ou sa définition sur une chaîne vide) peut également aider et vous permettra de negrep
pas transmettre la sortie deman
throughcol -b
.la source
NAME
dans le manuel bash est justeNAME
, non\b
.MAN_KEEP_FORMATTING
variable fonctionne exactement comme vous le dites. Je voulais juste souligner que ce n'est pas toujours le cas.