awking 从手册页获取命令选项

awking 从手册页获取命令选项

我正在尝试为不同的命令自动生成制表符补全。我将不同命令的手册页传输到 awk 中,然后搜索命令行选项(例如-shortopt --long-option),将每个命令打印在单独的行上:

for (i=1;i<NF;i++){
    if(match("\<-[0-9a-zA-Z_-]\+\>", $i)){
        print $i
    }
}

由于某种原因,这无法工作。使用单个反斜杠时,awk 会警告忽略转义序列\<,然后将其视为文字\\<。如果我使用两个反斜杠,awk 就会拒绝与适当的模式进行实际匹配(如果我在 vim 中打开手册页,然后运行该模式,则此方法有效,因此我认为该模式应该是正确的)。上面的代码片段位于一个文件中,然后我用它调用它man {section} {page} | awk -f find-options.awk,因此我认为我可以排除命令字符串被 bash 和 awk 多次解析的问题(如带有反斜杠的 awk FS)因为 awk 应该直接读取脚本文件。

答案1

man ls | col -bx | nawk '
{
    for (ii=1;ii<=NF;ii++) {
        if ( match($ii,/^(-[a-zA-Z0-9]|--[a-zA-Z0-9-]+)/) )
            opt[substr($ii,RSTART,RLENGTH)]++
     }  
} 
END { for (oo in opt) printf("%s\n",oo)  } '

这应该适用于任何“新”awk ( nawk, mawk, gawk)。

改变的事情:

  1. 循环变量名和差一错误
  2. match()埃德·莫顿指出,论证中的顺序错误
  3. 用于/.../文字正则表达式,不要转义+,并删除不正确的使用\< (它不会匹配,因为-不在“单词”中,只有字母、数字、下划线)
  4. 通过管道col -b删除退格/过冲
  5. 将所有观察到的选项保存在数组中以抑制输出中的重复项

观察到的转义错误是由于match()参数的错误顺序引起的,文字字符串中的“<”不需要也不应该被转义。仅\<在正则表达式(具有适当的/.../分隔符)中具有特殊含义。如果正则表达式是文字“字符串”或在变量中,则您可以"\\<"在文字字符串中使用以便\<在正则表达式中表示。

bash 完成包中有一个功能可以完成与您的目标类似的任务,它的_longopt功能是调用一个命令来--help动态生成完成,最终使用类似如下的内容:

compgen -W "$( LC_ALL=C $COMMAND --help 2>&1 | \
  sed -ne 's/.*\(--[-A-Za-z0-9]\{1,\}=\{0,1\}\).*/\1/p' | sort -u )"

您可能还会发现以下的实现(perl)help2man具有启发意义的是,这会处理“”或等效项的输出command --help以生成最小的手册页。


¹\<\> 零宽度断言是非 POSIX 并且现在不常见,在 PCRE 中\b(?<=\W)并且\b(?=\W)被使用。支持gawk是 GNU 主义,尽管没有这样的记录。 Solaris ERE 匹配也支持它们,尽管它awk不支持 — 它们也可以匹配字符串的开头或结尾,因此按预期工作(即使用/usr/xpg4/bin/grep -E)。

它们不匹配 GNU awk 中字符串的开头/结尾,但/-\<[0-9a-zA-Z_-]+\>/可以工作,已更改\<--\<匹配以下单词字符。

相关内容