【问题标题】:Is there a way to look for a flag in a man page?有没有办法在手册页中查找标志?
【发布时间】:2013-10-12 11:38:05
【问题描述】:

我正在尝试想出一种方法来在手册页中查找特定标志。通常,我输入'/' 搜索某些内容,然后使用“-Werror”之类的内容来查找特定标志。 问题是虽然有手册页(gcc 是现在激励我的那个) 在他们的文本中有很多对标志的引用,所以出现的次数很多。

这没什么大不了的,但也许可以做得更好。我想过寻找 '-O\n' 之类的东西,但它不起作用(可能是因为 man 程序不使用 C 转义?) 然后我尝试了man gcc | grep $'-O\n' 之类的方法,因为我有点记得 以美元符号开头的单引号字符串具有 bash 解释常见的 C 转义... 它不起作用,grep 回显了整个手册页。

这就是把我带到这里的原因:为什么?或者更确切地说,可以这样做吗?

【问题讨论】:

  • 另一种方法是使用explainshell.com,它给定一个带有选项的命令,使用从man 页面中提取的信息来解释每个选项,并使用一个漂亮的GUI;这是gcc -O 的结果:explainshell.com/explain?cmd=gcc+-O。请注意,使用的man 页面是 Ubuntu 的,因此该信息适用于 GNU 实用程序。
  • 我不久前发现了 explainshell,我很喜欢它,谢谢。好建议。
  • 所以基本上,您只需使用grep -- -ngrep -e -n 明确搜索-n,而不是将其作为标志传递给grep

标签: linux bash unix sh less-unix


【解决方案1】:

rici's helpful answer很好地解释了原来方法的问题。

不过,还有一点值得一提:

man 的输出包含格式化控制字符,这会干扰文本搜索

如果您在搜索之前通过管道传送到col -b,这些控制字符将被删除 - 请注意搜索结果也将是纯文本的副作用。

但是,grep 不是适合这项工作的工具;我建议使用awk如下获取-O的描述:

man gcc | col -b | awk -v RS= '/^\s+-O\n/'
  • RS=(一个空的输入记录分隔符)是一个 awk 习惯用法,它将输入分成非空行的块,因此匹配此类块开头的选项可确保 所有包含选项被返回。

如果您有 POSIX-features-only awk,例如 BSD/OSX awk,请使用此版本:

man gcc | col -b | awk -v RS= '/^[[:blank:]]+-O\n/'

显然,这样的命令键入起来有些麻烦,所以在下面找到generic bash function manopt,它从其返回指定命令的指定选项的描述man 页面。 (可能存在误报和误报,但总体而言效果很好。)

例子:

manopt gcc O          # search `man gcc` for description of `-O`
manopt grep regexp    # search `man grep` for description of `--regexp`
manopt find '-exec.*' # search `man find` for all actions _starting with_ '-exec'

bash 函数manopt() - 放入~/.bashrc,例如:

# SYNOPSIS
#   manopt command opt
#
# DESCRIPTION
#   Returns the portion of COMMAND's man page describing option OPT.
#   Note: Result is plain text - formatting is lost.
#
#   OPT may be a short option (e.g., -F) or long option (e.g., --fixed-strings);
#   specifying the preceding '-' or '--' is OPTIONAL - UNLESS with long option
#   names preceded only by *1* '-', such as the actions for the `find` command.
#
#   Matching is exact by default; to turn on prefix matching for long options,
#   quote the prefix and append '.*', e.g.: `manopt find '-exec.*'` finds
#   both '-exec' and 'execdir'.
#
# EXAMPLES
#   manopt ls l           # same as: manopt ls -l
#   manopt sort reverse   # same as: manopt sort --reverse
#   manopt find -print    # MUST prefix with '-' here.
#   manopt find '-exec.*' # find options *starting* with '-exec'
manopt() {
  local cmd=$1 opt=$2
  [[ $opt == -* ]] || { (( ${#opt} == 1 )) && opt="-$opt" || opt="--$opt"; }
  man "$cmd" | col -b | awk -v opt="$opt" -v RS= '$0 ~ "(^|,)[[:blank:]]+" opt "([[:punct:][:space:]]|$)"'
}

fish实现manopt()

贡献者Ivan Aracki

function manopt 
  set -l cmd $argv[1]
  set -l opt $argv[2] 
  if not echo $opt | grep '^-' >/dev/null
    if [ (string length $opt) = 1 ] 
      set opt "-$opt"
    else
      set opt "--$opt"
    end
  end
  man "$cmd" | col -b | awk -v opt="$opt" -v RS= '$0 ~ "(^|,)[[:blank:]]+" opt "([[:punct:][:space:]]|$)"'
end

【讨论】:

  • @AlexanderWeickmann:确实没有,因为jqman 页面的格式与ls 等标准实用程序的页面格式不同。
  • 我发现我必须稍微编辑一下。使用您的示例,我必须将其更改为MANWIDTH=160 man gcc | col -b | awk -v RS= '/-O,/'。前面的例子,设置了 MANDWITH,什么也没输出,我不知道为什么。我很想知道,但无论如何,谢谢!
【解决方案2】:

我怀疑你实际上并没有使用grep $'-O\n',而是grep 识别的一些标志。

从 grep 的角度来看,您只是在传递一个参数,并且该参数以 - 开头,因此它将被解释为一个选项。您需要执行grep -- -O$ 之类的操作来显式标记选项列表的末尾,或者使用grep -e -O$ 将模式显式标记为模式。无论如何,您不能在模式中包含换行符,因为 grep 模式实际上是由换行符分隔的模式列表,因此参数 $'foo\n' 实际上是两个模式,foo 和空字符串,空字符串将匹配每一行。

也许您搜索了标志 -e,因为它将模式作为参数,并且给它一个换行符作为参数将导致 grep 查找整个文件中的每一行。

对于大多数 GNU 程序,例如 gcc,您可能会发现 info 界面更易于导航,因为它包括参考链接、目录甚至索引。 info gcc 文档包含一个选项索引,非常有用。在某些 linux 发行版中,有些令人惊讶的是,它们自称为 GNU/linux 发行版,尽管 man 文件与基本软件一起分发,但有必要单独安装 info 软件包。例如,包含 gcc info 文件的 debian/ubuntu 软件包称为 gcc-doc。 (在包名中使用-doc 后缀很常见。)

对于gcc,您可以使用如下命令快速找到一个选项:

info gcc "option index" O

info gcc --index-search=funroll-loops

对于选项较少的程序,通常使用 info 的 -O 选项就足够了:

info -O gawk

【讨论】:

  • 谢谢你的信息,我去看看。
  • 我刚刚尝试了man gcc | grep -- $'-O\n',但没有成功。但是使用 `grep -- -e '-O$' 它确实......虽然现在我觉得很愚蠢,因为这显然会返回一个只包含'-O'的行,这根本没有用......跨度>
  • @ferhtgoldaraz:您可能想要使用-A1 或类似的(“-A NUM 在匹配行之后打印 NUM 行尾随上下文。”)
  • @rici:感谢您的澄清更新。 -e 实际上不一定regex 作为其参数(尽管选项名称很长,--regexp) - 它只是传递 的另一种机制多个 模式作为单独的选项 而不是单个多行字符串。因此,例如,对于-F(或作为fgrep 调用),-e 参数是固定(文字)字符串。另一种说法:传递给-e 的模式与没有它的模式相同(将多行字符串传递给-e 也会产生多个模式)。
  • @mklement0:是的,我没有在未编辑的文本中修复regex 这个词。为了彻底起见,我会改变这个词。
【解决方案3】:

问题是“man”使用了一个寻呼机,通常是“less”,它的手册页说明:

/pattern
    Search  forward  in  the file for the N-th line containing the pattern.
    N defaults to 1.  The pattern is a regular expression, as recognized by the
    regular expression library supplied by your system.  The search starts at the
    first line displayed (but see the -a and -j options, which change this).

因此可以尝试在手册页中查找“-O$”以找到单独存在于其中的标志 自己的线。虽然,在同一行中,一个标志后面跟着文本是很常见的, 所以这不能保证有效。

不过,grep 和 $'-O\n' 的问题仍然是个谜。

【讨论】:

  • 我不打算通过添加对我自己的问题的答案来欺骗系统或任何东西,我实际上是先查找它并提出this meta stack overflow question 解决可能的问题。
【解决方案4】:

我使用以下:

man some_command | col -b | grep -A5 -- 'your_request'

例子:

  • man man | col -b | grep -A5 -- '-K'

  • man grep | col -b | grep -A5 -- '-e patt'

你可以给它起别名。

【讨论】:

    【解决方案5】:

    manly Python 实用程序非常方便快速解释给定命令中使用的所有选项。

    注意它只输出选项描述的第一段。

    pip install manly
    
    $ manly blkid /dev/sda -o value -p
    
    blkid - locate/print block device attributes
    ============================================
    
          -o, --output format
                  Use  the  specified output format.  Note that the order of vari‐
                  ables and devices is not fixed.  See also option -s.  The format
                  parameter may be:
    
          -p, --probe
                  Switch to  low-level  superblock  probing  mode  (bypassing  the
                  cache).
    

    【讨论】:

      【解决方案6】:
      man gcc | grep "\-" 
      

      这很好用,因为它会显示所有标志,而且通常不会更多。

      编辑:我注意到我没有完全回答你的问题,但我希望我的建议可以被视为一个不错的选择。

      【讨论】:

      • 该搜索模式中的反斜杠毫无意义。无论有没有反斜杠,它都会返回 man gcc 的 12737 行中的 5160 行。您可以通过将其限制为看起来更像选项的内容来减少它:例如,man gcc | grep ' -[[:alpha::]]' 返回 3788 行。当然,gcc 有很多个选项,你很少真的想查看所有选项。
      【解决方案7】:

      man 基于环境变量(EDITOR,如果我没记错的话)。您可以将其从more(默认值)更改为例如emacs,然后在使用man 时在您的系统上打开一个emacs 会话,您可以在其中随意搜索和浏览。

      【讨论】:

        【解决方案8】:

        在大多数 bash 内置命令和许多其他命令中使用双破折号 (--) 来表示命令选项的结束

        https://unix.stackexchange.com/a/11382/204245

        如果没有双破折号,grep 会尝试使用您要查找的任何标志:

        $ man curl | grep -c # Looks for this c flag, but can't find one so throws the error below.
        usage: grep [-abcDEFGHhIiJLlmnOoqRSsUVvwxZ] [-A num] [-B num] [-C[num]]
            [-e pattern] [-f file] [--binary-files=value] [--color=when]
            [--context[=num]] [--directories=action] [--label] [--line-buffered]
            [--null] [pattern] [file ...]
        

        如果您使用双破折号来表示对grep 的输入结束,它的效果会更好一些,但您仍然会以每次 次匹配结束:

        $ man curl | grep -- -c
               --cacert <file>
                      certs file named 'curl-ca-bundle.crt', either in the same direc-
               --capath <dir>
                      curl to make SSL-connections much more  efficiently  than  using
                      --cacert if the --cacert file contains many CA certificates.
               --cert-status
               --cert-type <type>
               -E, --cert <certificate[:password]>
               --ciphers <list of ciphers>
        # ...many more matches......
        

        所以只需将标志括在引号中并在其前添加一个空格以仅匹配 -c 标志:

        $ man curl | grep -- " -c"
               -c, --cookie-jar <filename>
        

        这让我发疯了很多年。希望这会有所帮助。

        【讨论】:

          猜你喜欢
          • 2019-07-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-09-13
          • 1970-01-01
          相关资源
          最近更新 更多