
Ich versuche alles zu extrahierenBefehlszusammenfassungenaus den Manpages bei /usr/share/man/man1
Verwendung von:
#!/usr/bin/env bash
## synopses - extract all synopses in /usr/share/man/man1
cd /usr/share/man/man1
for i in *.gz; do
echo "$i:" | sed -E "s/.1.gz|.gz//g"
man "./$i" | sed -n '/^SYNOPSIS/,/^[A-Z][A-Z][A-Z]/p' | sed -e '1d; $d' | tr -s [:space:]
done
...der bereitstelltmancheErfolgsmaßstab - ich erhalte eine vollständige Ausgabe für Befehle vonAZuz. Aber ich bekomme auch viele Fehler aufstderrunter Verwendung von for i in ./*.gz; do man "$i"
sowohlfor i in *.gz; do man "./$i"
wie ich in eine Datei ausgebe( synopses > file
) 1 :
<standard input>:27: expected `;' after scale-indicator (got `o')
<standard input>:29: expected `;' after scale-indicator (got `o')
<standard input>:283: name expected (got `\{'): treated as missing
<standard input>:674: warning: macro `as',' not defined (possibly missing space after `as')
<standard input>:174: name expected (got `\{'): treated as missing
<standard input>:161: warning [p 1, 5.5i]: can't break line
<standard input>:594: warning [p 5, 3.8i, div `an-div', 0.0i]: can't break line
<standard input>:569: warning [p 6, 0.0i]: can't break line
<standard input>:147: warning [p 1, 1.8i]: can't break line
<standard input>:205: warning [p 2, 0.2i]: can't break line
<standard input>:525: warning [p 5, 4.5i]: can't break line
<standard input>:157: warning [p 1, 4.8i]: can't break line
<standard input>:351: warning [p 3, 1.8i, div `an-div', 0.0i]: can't break line
<standard input>:147: a space character is not allowed in an escape name
man: can't open man1/zshmisc.1: No such file or directory
man: -:423: warning: failed .so request
man: can't open man1/zshexpn.1: No such file or directory
man: -:423: warning: failed .so request
man: can't open man1/zshparam.1: No such file or directory
man: -:423: warning: failed .so request
man: can't open man1/zshoptions.1: No such file or directory
man: -:423: warning: failed .so request
man: can't open man1/zshbuiltins.1: No such file or directory
man: -:423: warning: failed .so request
man: can't open man1/zshzle.1: No such file or directory
man: -:423: warning: failed .so request
man: can't open man1/zshcompwid.1: No such file or directory
man: -:423: warning: failed .so request
man: can't open man1/zshcompsys.1: No such file or directory
man: -:423: warning: failed .so request
man: can't open man1/zshcompctl.1: No such file or directory
man: -:423: warning: failed .so request
man: can't open man1/zshmodules.1: No such file or directory
man: -:423: warning: failed .so request
man: can't open man1/zshcalsys.1: No such file or directory
man: -:423: warning: failed .so request
man: can't open man1/zshtcpsys.1: No such file or directory
man: -:423: warning: failed .so request
man: can't open man1/zshzftpsys.1: No such file or directory
man: -:423: warning: failed .so request
man: can't open man1/zshcontrib.1: No such file or directory
man: -:423: warning: failed .so request
<standard input>:423: can't open `man1/zshmisc.1': No such file or directory
<standard input>:424: can't open `man1/zshexpn.1': No such file or directory
<standard input>:425: can't open `man1/zshparam.1': No such file or directory
<standard input>:426: can't open `man1/zshoptions.1': No such file or directory
<standard input>:427: can't open `man1/zshbuiltins.1': No such file or directory
<standard input>:428: can't open `man1/zshzle.1': No such file or directory
<standard input>:429: can't open `man1/zshcompwid.1': No such file or directory
<standard input>:430: can't open `man1/zshcompsys.1': No such file or directory
<standard input>:431: can't open `man1/zshcompctl.1': No such file or directory
<standard input>:432: can't open `man1/zshmodules.1': No such file or directory
<standard input>:433: can't open `man1/zshcalsys.1': No such file or directory
<standard input>:434: can't open `man1/zshtcpsys.1': No such file or directory
<standard input>:435: can't open `man1/zshzftpsys.1': No such file or directory
<standard input>:436: can't open `man1/zshcontrib.1': No such file or directory
Was <standard input>
bedeuten diese Fehler (ist etwas entgangen?) und warum werden man
einige Dateien am Ende nicht gefunden? Wie kann ich das robuster/effizienter machen?
1. Es scheint, dass die Fehler aufstderrsind gleich, egal welche Implementierung/Lösung ich für dieselben Daten verwende. Das ist auffällig.
Antwort1
Man kann nicht einfach weglaufenEs sieht aus wie dudürfenlaufen man foo.gz
man foo.1.gz
, aber die Verwendung -l
scheint sauberer zu sein. Von man man
:
-l, --local-file
Activate `local' mode. Format and display local manual files
instead of searching through the system's manual collection.
Each manual page argument will be interpreted as an nroff source
file in the correct format. No cat file is produced. If '-' is
listed as one of the arguments, input will be taken from stdin.
When this option is not used, and man fails to find the page
required, before displaying the error message, it attempts to
act as if this option was supplied, using the name as a filename
and looking for an exact match.
Ihr Skript sollte also etwa so aussehen:
#!/usr/bin/env bash
## synopses - extract all synopses in /usr/share/man/man1
## No need to cd into the directory, you can just use globs
for i in /usr/share/man/man1/ajc*.gz; do
## This will print the name of the command.
basename "${i//.1.gz}"
man -l "$i" |
awk '/^SYNOPSIS/{a=1; getline}
(/^[a-zA-z0-9_]/ && a==1){a=0}
(a==1 && /./){print}' | tr -s [:space:]
done
Der awk
von mir angegebene Befehl funktioniert besser als Ihr Ansatz (testen Sie ihn man ajc
beispielsweise an) und funktioniert jetzt auch bei mehrzeiligen Zusammenfassungen. Die meisten der angezeigten Fehler sind irrelevant, andere waren auf die Art und Weise zurückzuführen, wie Sie mit Dateinamen umgegangen sind. Lassen Sie mich wissen, ob dieser besser funktioniert.
Antwort2
Die aufgetretenen Fehler werden alle hier behandelt:
man man
MANWIDTH
- Wenn$MANWIDTH
gesetzt ist, wird sein Wert als Zeilenlänge verwendet, für die Handbuchseiten formatiert werden sollen. Wenn es nicht gesetzt ist, werden Handbuchseiten mit einer Zeilenlänge formatiert, die dem aktuellen Terminal entspricht (mit ioctl(2), falls verfügbar, dem Wert von$COLUMNS
oder mit 80 Zeichen, falls keines von beiden verfügbar ist). Handbuchseiten werden nur gespeichert, wenn die Standardformatierung verwendet werden kann, d. h. wenn die Zeilenlänge des Terminals zwischen 66 und 80 Zeichen liegt.
MAN_KEEP_FORMATTING
- Wenn die Ausgabe nicht an ein Terminal geleitet wird (z. B. an eine Datei oder eine Pipe), werden Formatierungszeichen normalerweise verworfen, um das Lesen des Ergebnisses ohne Spezialwerkzeuge zu erleichtern. Wenn jedoch$MAN_KEEP_FORMATTING
auf einen beliebigen nicht leeren Wert gesetzt ist, werden diese Formatierungszeichen beibehalten. Dies kann für Wrapper um man nützlich sein, die Formatierungszeichen interpretieren können.
MAN_KEEP_STDERR
- Wenn die Ausgabe an ein Terminal (normalerweise an einen Pager) geleitet wird, wird normalerweise jede Fehlerausgabe des Befehls, der zum Erstellen formatierter Versionen von Handbuchseiten verwendet wird, verworfen, um Störungen der Anzeige des Pagers zu vermeiden. Programme wiegroff
erzeugen oft relativ geringfügige Fehlermeldungen über typografische Probleme wie schlechte Ausrichtung, die unansehnlich und im Allgemeinen verwirrend sind, wenn sie zusammen mit der Handbuchseite angezeigt werden. Einige Benutzer möchten sie jedoch trotzdem sehen, daher$MAN_KEEP_STDERR
wird die Fehlerausgabe wie üblich angezeigt, wenn auf einen beliebigen nicht leeren Wert gesetzt ist.
Und nun dazu, wie Sie das andere tun könnten:
Ich denke, das hier macht, was Sie wollen:
for f in /usr/share/man/man1/*gz ; do
man -P "sed -ne '1,/^[Nn]/d;/^ /{H;b}
/^[Ss]..[Yy]..[Nn]/{g;:n
N;/\n\(\n\)[^ ].*/!bn;s//\1/
s/.\x08//g;s/\(\n\) */\1/g;
w /dev/stderr' -ne '};/./q'" -l "$f"
done 2>~/file
Es gibt an, dass es sed
sich um die Zeile handelt PAGER
, und gibt dann nur die folgende Zeile ausNAMEund die folgendenZUSAMMENFASSUNGbis es auf eine andere Zeile trifft, die mit etwas anderem als a beginnt <space>
. Es drucktNichtswenn die erste Zeile, die nicht damit beginnt, <space>
folgtNAMEstimmt nicht mit begin überein [Ss][Yy][Nn]
. In jedem Fall wird das Lesen der Datei in der zweiten Zeile beendet, die nachNAMEdas nicht mit beginnt <space>
. Es löscht führende <spaces>
und alle \b
Ackslashs aus der Ausgabe.
Ich habe es for
gerade in einer Schleife ausgeführt und es hat man
in nur einer Minute meine gesamte Bibliothek durchlaufen.
man
passt seine Ausgabe an, je nachdem, ob es in ein Terminal oder eine Pipe/Datei schreibt. Wenn Sie ihm also sagen, dass er das tun soll, verzichtet er ganz auf den PAGER. Das war unerwartet. Aber ich habe es ausgetrickst und die w
Rite-Funktion von sed verwendet, um in >&2 zu schreiben und das umzuleiten, also hat es nichts gemerkt.
Eine Anmerkung jedoch: Es ist vielleicht die bessere Vorgehensweise von @terdon. Sie können dies zwar einfacher anpassen, da Sie eine sed
pro Datei erhalten, und die Formatierung ist etwas besser, da sie nicht versucht, auf die Breite eines Terminals zu passen, diese \Backslashes werden anscheinend jedoch man
nicht in ein geschrieben |pipe
.