Inspect Man Page Headers and Filters with lexgrog
You will use lexgrog to check a man page's parsed name and description, see which preprocessors it needs, and separate a malformed page from a bad command invocation. The examples use man-db 2.12.0, installed here as package version 2.12.0-4build2. Allow about ten minutes. You need a shell and a readable man page source or preformatted cat page. These checks are read-only and do not require sudo.
The route
Jump straight to the step you need, or tick off Done means at the end.
1. Check the installed command
Start by checking which executable will run and which release it reports:
$ command -v lexgrog
/usr/bin/lexgrog
$ lexgrog --version
lexgrog 2.12.0
The man page describes the command as a parser for header information in man pages. It accepts one or more files, and a file named - means standard input. Compressed input is decompressed automatically, so an installed .gz man page can be passed directly.
Checkpoint
If command -v finds nothing, install man-db using your normal package-management process before continuing. Do not diagnose a missing executable as a parsing failure.
2. Read the NAME data that whatis uses
With no mode options, lexgrog defaults to parsing man source and displaying whatis information. Point it at the installed lexgrog page:
$ lexgrog /usr/share/man/man1/lexgrog.1.gz
/usr/share/man/man1/lexgrog.1.gz: "lexgrog - parse header information in man pages"
The result comes from the page's NAME section. The text is the name and short description that apropos and whatis can index. A successful parse does not validate every part of the document or prove that the examples in it work.
Pass several files when checking a batch. Each file gets its own result, which makes a simple scan easy to review:
$ lexgrog /usr/share/man/man1/lexgrog.1.gz /usr/share/man/man1/man.1.gz
/usr/share/man/man1/lexgrog.1.gz: "lexgrog - parse header information in man pages"
/usr/share/man/man1/man.1.gz: "man - an interface to the system reference manuals"
3. Inspect the preprocessing filters
Use --filters when you need to know which preprocessing pipeline lexgrog has inferred. Combine it with --whatis to retain the description as well:
$ lexgrog --filters --whatis /usr/share/man/man1/lexgrog.1.gz
/usr/share/man/man1/lexgrog.1.gz (-): "lexgrog - parse header information in man pages"
The parenthesised marker is the filter result for this page. A page that uses requests such as .tbl, .eqn or .pic can produce a different marker. Use the output as a diagnostic hint about the page's source, not as a command line to copy into nroff without checking the page and your formatter.
If you only need the filter information, omit --whatis:
$ lexgrog --filters /usr/share/man/man1/lexgrog.1.gz
/usr/share/man/man1/lexgrog.1.gz (-)
4. Choose man source or cat-page parsing explicitly
The default is --man, for roff source. Use --cat only when the input is already a preformatted cat page:
$ lexgrog --man /usr/share/man/man1/lexgrog.1.gz
/usr/share/man/man1/lexgrog.1.gz: "lexgrog - parse header information in man pages"
--man and --cat are alternatives, not cumulative modes. Supplying both is a usage error. A cat page is not simply a man source file with a different extension, so use the mode that matches the actual file content. If you are unsure, inspect the file's provenance and try the default first.
5. Check a page in a script
For automation, the exit status is more reliable than matching the output wording. The documented statuses are 0 for success, 1 for a usage error, and 2 when lexgrog could not parse one or more inputs:
lexgrog --man /path/to/page.1.gz
status=$?
case "$status" in
0) printf '%s\n' 'man page parsed' ;;
1) printf '%s\n' 'lexgrog usage error' >&2; exit 1 ;;
2) printf '%s\n' 'man page parse failed' >&2; exit 2 ;;
*) printf 'unexpected lexgrog status %s\n' "$status" >&2; exit 1 ;;
esac
For a broken page, the normal whatis output includes parse failed. Capture the status immediately after lexgrog, as any later command would replace $?. Keep the input path in the report so a batch check identifies the failing file.
6. Fix the NAME section at its source
When the parser fails, inspect the source rather than trying random flags. Traditional man macros normally put the command name and its short description in a .SH NAME section, with the name, a literal escaped hyphen, and the description:
.SH NAME
tool \- inspect an example file
Several names may be comma-separated. Separate descriptions can use a break or paragraph request. BSD-derived mdoc pages use .Sh NAME, .Nm and .Nd instead. Names containing whitespace are ignored by the parser, because accepting them could produce unsafe or misleading whatis entries.
Do not rename a section merely to make a check pass. A section called .SH MYPROGRAM, or free-form text without a name and description, can leave mandb without the data it needs. After editing a page, rerun lexgrog against the exact installed or staged file and check the exit status.
7. Avoid the common traps
- Use
--manfor source and--catfor preformatted output. They cannot be combined. - Use
--encodingonly when the guessed character set is wrong. It changes decoding, not the page's NAME syntax. - Files using
.sorequests are resolved correctly only when installed in a proper manual-page hierarchy. - Do not use
sudojust to parse a readable page. Elevated access is relevant only if filesystem permissions prevent reading the input. - Do not overwrite a packaged page while testing a fix. Work on a copy in a writable directory, then install it through your normal packaging or deployment workflow if that is genuinely required.
Done means
lexgrog --versionreports the expected installed release.- The target page returns its expected NAME description with the default mode.
- Filter checks use
--filtersand are interpreted as diagnostics. - Scripts branch on status 0, 1 and 2 without losing
$?. - A parse failure is repaired in the page's NAME section, not hidden with an unrelated option.