Me encuentro con un comportamiento extraño al intentar grep una página de manual en macOS. Por ejemplo, la página de manual de Bash claramente tiene una aparición de la cadena NAME
:
$ man bash | head -5 | tail -1
NAME
Y si busco name
, obtengo resultados, pero si NAME
busco, no:
$ man bash | grep 'NAME'
$ man bash | grep NAME
He intentado otras palabras en mayúscula que sé que están allí, y la búsqueda de SHELL
resultados no produce nada mientras que la búsqueda de BASH
resultados arroja resultados.
¿Que está pasando aqui?
Actualización : ¡Gracias por todas las respuestas! Pensé que valía la pena agregar el contexto en el que me encontré con esto. Quería escribir una función bash para ajustar man
y, en los casos en que he intentado buscar la página del manual para un shell incorporado, salte a la sección correspondiente de la página del manual de Bash. Puede haber una mejor manera, pero esto es lo que tengo actualmente:
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
}
fuente
man bash | grep NAME
Funciona como se esperaba.help
comando bash para obtener su información.help
resultados dejan demasiado afuera. Echa un vistazo ahelp complete
lacomplete
sección enman bash
, por ejemplo.Respuestas:
Si agrega un comando
| sed -n l
a esetail
comando, para mostrar caracteres no imprimibles, probablemente verá algo como:Es decir, cada personaje está escrito como
X
RetrocesoX
. En las terminales modernas, el personaje termina siendo escrito sobre sí mismo (como Backspace aka BS aka\b
aka^H
es el personaje que mueve el cursor una columna hacia la izquierda) sin diferencia. Pero en las máquinas de escribir antiguas, eso haría que el personaje apareciera en negrita, ya que recibe el doble de tinta.Aún así, los localizadores como
more
/less
entienden que el formato significa negrita, por lo que sigue siendo esoroff
lo que hace que el texto aparezca en negrita.Algunas implementaciones de hombre llamarían
roff
de una manera que esas secuencias no se usan (o llamarían internamentecol -b -p -x
para despojarlas como en el caso de laman-db
implementación (a menos que se establezca laMAN_KEEP_FORMATTING
variable de entorno)), y no invoquen un buscapersonas cuando detecten la salida no va a una terminal (porman bash | grep NAME
lo que funcionaría allí), pero no a la suya.Puede usar
col -b
para eliminar esas secuencias (también hay otros tipos (_
BSX
) para subrayar).Para los sistemas que usan GNU
roff
(como GNU o FreeBSD), puede evitar que esas secuencias se usen en primer lugar asegurándose de-c -b -u
que se pasen las opcionesgrotty
, por ejemplo, asegurándose de-P-cbu
que se pasen las opcionesgroff
.Por ejemplo, creando una secuencia de comandos de contenedor llamada que
groff
contiene:Que pones delante de / usr / bin / groff
$PATH
.Con macOS '
man
(también usando GNUroff
), puede crear unman-no-overstrike.conf
con:Y llama
man
como:Aún con GNU
roff
, si establece laGROFF_SGR
variable de entorno (o no establece laGROFF_NO_SGR
variable dependiendo de cómo se hayan establecido los valores predeterminados en el momento de la compilación), entoncesgrotty
(siempre que no se pase la-c
opción) utilizará secuencias de escape de terminal ANSI SGR en su lugar de esos trucos BS para atributos de personaje.less
Comprenderlos cuando se llama con la-R
opción.El hombre de FreeBSD llama
grotty
con la-c
opción a menos que esté pidiendo colores configurando la variable MANCOLOR (en cuyo caso-c
no se pasagrotty
ygrotty
vuelve al valor predeterminado de usar secuencias de escape ANSI SGR allí).Trabajaré allí.
En Debian, GROFF_SGR no es el valor predeterminado. Si lo haces:
sin embargo, debido a que
man
stdout no es una terminal, se encarga de pasar también unaGROFF_NO_SGR
variable agrotty
(supongo que puede usarsecol -bpx
para eliminar las secuencias BS yacol
que no sabe cómo eliminar las secuencias SGR, aunque todavía lo hace conMAN_KEEP_FORMATTING
) que anula nuestraGROFF_SGR
. Puedes hacer en su lugar:(en un terminal) para tener las secuencias de escape SGR.
Esa vez, notará que algunos de esos NOMBRES aparecen en negrita en el terminal (y en un
less -R
buscapersonas). Si alimenta la salida ased -n l
(MANPAGER='sed -n /NAME/l'
), verá algo como:¿Dónde
\e[1m
está la secuencia para habilitar negrita en terminales compatibles con ANSI y\e[0m
la secuencia para revertir todos los atributos SGR al valor predeterminado?En ese texto
grep NAME
funciona como ese texto contieneNAME
, pero aún podría tener problemas si busca texto donde solo partes de él están en negrita / subrayado ...fuente
sed -n l
como un sustituto deod
.Si observa cualquier página del manual, notará que los encabezados están en negrita. Esto se logra formateándolos con caracteres de control. Para poder
grep
gustar lo que quieres, estos deben ser eliminados.La
col
utilidad se puede usar para esto:La
-b
opción tiene la siguiente descripción en OpenBSD :Linux el
col
manual (en Ubuntu) no tiene la última oración allí (pero funciona de la misma manera).En Linux, desarmar la
MAN_KEEP_FORMATTING
variable de entorno (o configurarlo en una cadena vacía) también puede ayudar, y le permitirá hacerlogrep
sin pasar la salida de aman
travéscol -b
.fuente
NAME
manual de bash es simplementeNAME
no\b
.MAN_KEEP_FORMATTING
variable funciona exactamente como tú dices. Solo quería señalar que ese no es siempre el caso.