我正在尝试为不同的命令自动生成制表符补全。我将不同命令的手册页传输到 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
)。
改变的事情:
- 循环变量名和差一错误
match()
埃德·莫顿指出,论证中的顺序错误- 用于
/.../
文字正则表达式,不要转义+
,并删除不正确的使用\<
(它不会匹配,因为-
不在“单词”中,只有字母、数字、下划线) - 通过管道
col -b
删除退格/过冲 - 将所有观察到的选项保存在数组中以抑制输出中的重复项
观察到的转义错误是由于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_-]+\>/
可以工作,已更改\<-
为-\<
匹配以下单词字符。