Intereting Posts
Как построить одномерные данные с погрешностью в LibreOffice Calc? Что делает $ {3 #?}? «Незаконная инструкция» на статическом бинарном MIPS Как создать md5-файл для каждой папки в рекурсивном диске? Почему scp с сжатием занимает больше времени, чем без сжатия Как установить логический том? почему у меня есть два разных результата, если я запускаю программу через терминал (от имени root) или /etc/init.d(or /etc/rc.local) Отсутствуют символы стека с первичным отчетом perf_event, несмотря на сборник -fno-omit-frame-pointer SQLPLUS с циклами сценариев оболочки Временно ограничьте логины для пользователя одним IP Вызовите сценарий Linux с языка сценариев Есть ли способ настроить vim для запуска внешних команд через cpanel jailshell? запуск ./install как root Какая самая «правильная» точка монтирования для постоянного раздела NTFS? Настройка виртуальных хостов Apache в дополнительном файле

Как вы правильно извлекаете все синонимы команд из man-страниц в / usr / share / man / man1?

Я пытаюсь извлечь все синонимы команд из manpages в /usr/share/man/man1 используя:

 #!/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/,/^[AZ][AZ][AZ]/p' | sed -e '1d; $d' | tr -s [:space:] done 

… который обеспечивает некоторый успех – я получаю полный вывод для команд от a до z . Но я также получаю много ошибок на stderr, используя оба for i in ./*.gz; do man "$i" for i in ./*.gz; do man "$i" и for i in *.gz; do man "./$i" for i in *.gz; do man "./$i" как я for i in *.gz; do man "./$i" в файл ( 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 

Что это за ошибки <standard input> (что-то ускользнуло?) И почему man заканчивает, не найдя некоторые файлы? Как я могу сделать это более надежным / эффективным?


1. Кажется, что ошибки в stderr одинаковы независимо от того, какую реализацию / решение я использую для одних и тех же данных. Это поразительно.

Вы не можете просто запустить man foo.gz Похоже, вы можете запустить man foo.1.gz но с помощью -l кажется более чистым. От 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. 

Итак, ваш скрипт должен выглядеть примерно так:

 #!/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 

Команда awk я даю, работает лучше, чем ваш подход (например, проверьте его на man ajc ), а теперь также работает над многострочными синопсами. Большинство ошибок, которые вы видите, неактуальны, другие были связаны с тем, как вы обрабатывали имена файлов. Дайте мне знать, работает ли это лучше.

Что касается ошибок, с которыми вы сталкиваетесь, все они рассматриваются здесь:

 man man 

MANWIDTH – Если задано значение $MANWIDTH , его значение используется как длина строки, для которой нужно отформатировать страницы вручную. Если он не установлен, страницы руководства будут отформатированы с длиной строки, соответствующей текущему терминалу (используя доступную ioctl (2), значение $COLUMNS или возврат к 80 символам, если они не доступны). Страницы Cat будут сохранены только в том случае, если можно использовать форматирование по умолчанию, то есть когда длина линии терминала составляет от 66 до 80 символов.

MAN_KEEP_FORMATTING – Обычно, когда вывод не направляется на терминал (например, в файл или канал), символы форматирования отбрасываются, чтобы облегчить чтение результата без специальных инструментов. Однако, если $MAN_KEEP_FORMATTING настроено на любое непустое значение, эти символы форматирования сохраняются. Это может быть полезно для оберток вокруг человека, которые могут интерпретировать символы форматирования.

MAN_KEEP_STDERR – Обычно, когда вывод направляется на терминал (обычно на пейджер), любая ошибка, выводимая из команды, используемой для создания форматированных версий страниц руководства, отбрасывается, чтобы не мешать отображению пейджера. Такие программы, как groff часто создают относительно небольшие сообщения об ошибках о типографских проблемах, таких как плохое выравнивание, которые неприглядны и обычно запутываются при отображении вместе с страницей руководства. Однако некоторые пользователи все равно хотят их увидеть, поэтому, если $MAN_KEEP_STDERR установлен на любое непустое значение, вывод ошибки будет отображаться как обычно.

И теперь о том, как вы могли бы сделать другое:

Я думаю, что это делает то, что вы хотите:

 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 

Он указывает, что sed является PAGER а затем выводит только строку, следующую за NAME, и те, которые следуют за SYNOPSIS, пока не встретит какую-либо другую строку, начинающуюся с чего-либо другого, кроме <space> . Он ничего не печатает, если первая строка, не начинающаяся с <space> которая следует за NAME , не соответствует началу [Ss][Yy][Nn] . В каждом случае он полностью перестает читать файл во второй строке, с которой он сталкивается, следуя NAME, которое не начинается с <space> . Он очищает ведущие <spaces> и все \b ackslashes от результата.

Я запустил его в цикле for только сейчас, и он зациклился на всей моей библиотеке всего за минуту.

man настраивает свой вывод на основе того, записывает ли он терминал или канал / файл. Поэтому, если вы скажете, что это делает, то он полностью отказывается от PAGER. Это было неожиданно. Но я обманул ее и использовал функцию sed для записи в> & 2 и перенаправил ее так, чтобы она не была более мудрой.

Заметка – хотя это может быть @ terdon's – лучший способ пойти. Хотя вы можете адаптировать это проще, потому что вы получаете sed за файл, а форматирование немного лучше, потому что оно не пытается соответствовать ширине терминала, по-видимому, man не записывает эти обратные слэши в |pipe .