Występują dziwne zachowania, gdy próbuję grepować stronę podręcznika systemowego w systemie macOS. Na przykład strona podręcznika Bash ma wyraźnie wystąpienie ciągu NAME
:
$ man bash | head -5 | tail -1
NAME
A jeśli grepuję za name
, to dostaję wyniki, ale jeśli grepuję za NAME
, nie:
$ man bash | grep 'NAME'
$ man bash | grep NAME
Próbowałem innych wielkich liter, o których wiem, że tam są, i szukanie wyników SHELL
nic nie daje, podczas gdy wyszukiwanie BASH
wyników daje wyniki.
Co tu się dzieje?
Aktualizacja : Dziękujemy za wszystkie odpowiedzi! Pomyślałem, że warto dodać kontekst, w którym na to wpadłem. Chciałem napisać funkcję bash do zawinięcia, man
a w przypadkach, gdy próbowałem wyszukać stronę podręcznika dla wbudowanej powłoki, przeskocz do odpowiedniej sekcji strony podręcznika Bash. Może być lepszy sposób, ale oto co mam obecnie:
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
}
źródło
man bash | grep NAME
działa zgodnie z oczekiwaniami.help
polecenia bash, aby uzyskać jego informacje.help
wyniki zbyt wiele pomijają. Sprawdź nahelp complete
przykładcomplete
sekcję wman bash
.Odpowiedzi:
Jeśli dodasz
| sed -n l
do tegotail
polecenia, aby wyświetlać znaki niedrukowalne, prawdopodobnie zobaczysz coś takiego:Oznacza to, że każdy znak jest pisany jako
X
BackspaceX
. Na nowoczesnych terminalach znak kończy się nad sobą (ponieważ Backspace aka BS aka\b
aka^H
to znak, który przesuwa kursor o jedną kolumnę w lewo) bez różnicy. Ale w starożytnych maszynach do pisania to sprawiałoby, że postać pojawiała się pogrubioną czcionką, ponieważ otrzymywała dwa razy więcej atramentu.Mimo to, pagery takie jak
more
/less
do rozumieją ten format jako pogrubiony, więc nadal toroff
robi, aby uzyskać pogrubiony tekst.Niektóre implementacje man wywoływałyby
roff
w taki sposób, że te sekwencje nie byłyby używane (lub byłyby wywoływane wewnętrznie,col -b -p -x
aby je rozebrać, tak jak w przypadkuman-db
implementacji (chyba żeMAN_KEEP_FORMATTING
ustawiono zmienną środowiskową)) i nie wywoływały pagera po wykryciu wyniku nie jedzie do terminalu (więcman bash | grep NAME
by tam działał), ale nie twój.Możesz użyć
col -b
do usunięcia tych sekwencji (istnieją również inne typy (_
BSX
) również dla podkreślenia).W przypadku systemów korzystających z GNU
roff
(takich jak GNU lub FreeBSD) możesz uniknąć używania tych sekwencji, upewniając się, że-c -b -u
opcje zostały przekazanegrotty
, na przykład upewniając się, że-P-cbu
opcje zostały przekazanegroff
.Na przykład poprzez utworzenie skryptu opakowania o nazwie
groff
zawierającego:Które umieściłeś przed / usr / bin / groff
$PATH
.W systemie macOS '
man
(również używającym GNUroff
) możesz utworzyćman-no-overstrike.conf
:I zadzwoń
man
jako:Nadal w GNU
roff
, jeśli ustawiszGROFF_SGR
zmienną środowiskową (lub nie ustawiszGROFF_NO_SGR
zmiennej w zależności od tego, jak domyślne zostały ustawione w czasie kompilacji), wtedygrotty
(o ile nie zostanie przekazana-c
opcja) użyje zamiast tego sekwencji ucieczki terminala ANSI SGR tych sztuczek BS dla atrybutów postaci.less
zrozumieć je, gdy zostanie wywołany z-R
opcją.Man wywołuje FreeBSD
grotty
z tą-c
opcją, chyba że pytasz o kolory , ustawiając zmienną MANCOLOR (w którym-c
to przypadku nie jest przekazywanygrotty
igrotty
powraca do domyślnego użycia sekwencji specjalnych ANSI SGR).będzie tam działać.
W Debianie GROFF_SGR nie jest domyślny. Jeśli zrobisz:
jednak ponieważ standardowe
man
wyjście nie jest terminalem, na siebie spoczywa również obowiązek przekazaniaGROFF_NO_SGR
zmiennej dogrotty
(przypuszczam, że może on użyćcol -bpx
do rozebrania sekwencji BS, ponieważcol
nie wie, jak rozebrać sekwencje SGR, mimo że nadal robi to zMAN_KEEP_FORMATTING
), co zastępuje naszeGROFF_SGR
. Możesz zamiast tego:(w terminalu), aby mieć sekwencje specjalne SGR.
Tym razem zauważysz, że niektóre z tych NAZW są pogrubione na terminalu (i na
less -R
pagerze). Jeśli podasz wynik dosed -n l
(MANPAGER='sed -n /NAME/l'
), zobaczysz coś takiego:Gdzie
\e[1m
jest sekwencja, aby włączyć pogrubienie w terminalach kompatybilnych z ANSI, a\e[0m
sekwencja, aby przywrócić wszystkie atrybuty SGR do wartości domyślnej.Ten tekst
grep NAME
działa tak, jak on zawiera tekstNAME
, ale nadal możesz mieć problemy, jeśli szukasz tekstu, w którym tylko jego części są pogrubione / podkreślone ...źródło
sed -n l
jako substytutod
.Jeśli spojrzysz na jakąkolwiek stronę podręcznika, zauważysz, że nagłówki są pogrubione. Osiąga się to poprzez sformatowanie ich za pomocą znaków kontrolnych. Aby móc
grep
polubić to, co chcesz, należy je rozebrać.col
Narzędzie może być wykorzystywane do tego:-b
Opcja ma następujący opis w OpenBSD :Linux
col
instrukcja (na Ubuntu) nie zawiera ostatniego zdania (ale działa w ten sam sposób).W systemie Linux, wyłączające
MAN_KEEP_FORMATTING
zmienną środowiskową (lub ustawienie go na pusty ciąg znaków) może również pomóc, a pozwoli Cigrep
bez przechodzenia wyjścieman
poprzezcol -b
.źródło
NAME
w bash jest po prostuNAME
nie\b
.MAN_KEEP_FORMATTING
zmienna działa dokładnie tak, jak mówisz. Chciałem tylko zaznaczyć, że nie zawsze tak jest.