Estou tendo um comportamento estranho ao tentar grep uma página de manual no macOS. Por exemplo, a página do manual Bash claramente tem uma ocorrência da sequência NAME
:
$ man bash | head -5 | tail -1
NAME
E se eu grep for name
, obtenho resultados, mas se eu grep for NAME
, não:
$ man bash | grep 'NAME'
$ man bash | grep NAME
Eu tentei outras palavras em maiúsculas que eu sei que estão lá, e a pesquisa SHELL
não produz nada, enquanto a pesquisa BASH
produz resultados.
Oque esta acontecendo aqui?
Atualização : Obrigado por todas as respostas! Eu pensei que valeria a pena adicionar o contexto em que me deparei com isso. Eu queria escrever uma função bash para quebrar man
e, nos casos em que tentei procurar na página do manual por um shell incorporado, pule para a seção relevante da página do manual Bash. Pode haver uma maneira melhor, mas aqui está o que eu tenho atualmente:
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
}
fonte
man bash | grep NAME
funciona como esperado.help
comando bash para obter suas informações.help
resultados deixam muito de fora. Confirahelp complete
acomplete
seção emman bash
, por exemplo.Respostas:
Se você adicionar um
| sed -n l
a essetail
comando, para mostrar caracteres não imprimíveis, provavelmente verá algo como:Ou seja, cada caractere é escrito como
X
BackspaceX
. Nos terminais modernos, o caractere acaba sendo escrito sobre si mesmo (como Backspace aka BS aka\b
aka^H
é o caractere que move o cursor uma coluna para a esquerda) sem diferença. Mas nas tele-máquinas de escrever antigas, isso faria com que o personagem aparecesse em negrito, pois recebe duas vezes mais tinta.Ainda assim, os pagers gostam
more
/less
entendem esse formato como negrito, e ainda é o queroff
faz com a saída de texto em negrito.Algumas implementações humanas chamariam de
roff
maneira que essas seqüências não sejam usadas (ou chamarão internamentecol -b -p -x
para removê-las como no caso daman-db
implementação (a menos que aMAN_KEEP_FORMATTING
variável de ambiente esteja definida)) e não invoquem um pager quando detectarem a saída não está indo para um terminal (porman bash | grep NAME
isso funcionaria lá), mas não o seu.Você pode usar
col -b
para remover essas seqüências (existem outros tipos (_
BSX
) e também sublinhados).Para sistemas que usam GNU
roff
(como GNU ou FreeBSD), você pode evitar que essas sequências sejam usadas em primeiro lugar, certificando-se de que as-c -b -u
opções sejam passadasgrotty
, por exemplo, certificando-se de que as-P-cbu
opções sejam passadasgroff
.Por exemplo, criando um script de wrapper chamado
groff
contendo:Que você coloca à frente de / usr / bin / groff
$PATH
.Com o macOS '
man
(também usando o GNUroff
), você pode criar umman-no-overstrike.conf
com:E ligue
man
como:Ainda com o GNU
roff
, se você definir aGROFF_SGR
variável de ambiente (ou não aGROFF_NO_SGR
variável, dependendo de como os padrões foram definidos no tempo de compilação), entãogrotty
(contanto que não seja aprovada a-c
opção) usará as seqüências de escape do terminal ANSI SGR desses truques de BS para atributos de caracteres.less
entendê-los quando chamados com a-R
opçãoO homem do FreeBSD chama
grotty
com a-c
opção, a menos que você esteja solicitando cores , configurando a variável MANCOLOR (nesse caso,-c
não é passada paragrotty
egrotty
volta ao padrão de usar as seqüências de escape ANSI SGR).vai trabalhar lá.
No Debian, GROFF_SGR não é o padrão. Se você fizer:
no entanto, como
man
o stdout não é um terminal, também é possível passar umaGROFF_NO_SGR
variável paragrotty
(suponho que ele possa ser usadocol -bpx
para extrair as seqüências BS, poiscol
não sabe como extrair as seqüências SGR, mesmo que ainda faz isso comMAN_KEEP_FORMATTING
) que substitui o nossoGROFF_SGR
. Você pode fazer:(em um terminal) para ter as seqüências de escape do SGR.
Nesse momento, você notará que alguns desses NOME s aparecem em negrito no terminal (e em um
less -R
pager). Se você alimentar a saída parased -n l
(MANPAGER='sed -n /NAME/l'
), verá algo como:Onde
\e[1m
está a sequência para ativar negrito nos terminais compatíveis com ANSI e\e[0m
a sequência para reverter todos os atributos SGR para o padrão.Nesse texto
grep NAME
funciona como o texto contémNAME
, mas você ainda pode ter problemas se procurar texto em que apenas partes dele estejam em negrito / sublinhado ...fonte
sed -n l
como um substitutood
.Se você olhar para qualquer página de manual, notará que os cabeçalhos estão em negrito. Isso é conseguido através da formatação com caracteres de controle. Para poder
grep
gostar do que você quer, eles precisam ser retirados.O
col
utilitário pode ser usado para isso:A
-b
opção possui a seguinte descrição no OpenBSD :O
col
manual do Linux (no Ubuntu) não tem a última frase lá (mas funciona da mesma maneira).No Linux, desmarcar a
MAN_KEEP_FORMATTING
variável de ambiente (ou defini-la como uma sequência vazia) também pode ajudar e permitirá que vocêgrep
, sem passar a saída doman
meiocol -b
.fonte
NAME
manual do bash é apenasNAME
, não\b
.MAN_KEEP_FORMATTING
variável funciona exatamente como você diz. Eu só queria ressaltar que nem sempre é o caso.