使用egrep和awk在两个模式之间获取文本

时间:2015-12-04 23:58:12

标签: regex bash awk grep

我试图解析命令的帮助文件以获取命令除外的所有参数。

以下是帮助文件中的一些文字:

* --digest:
  Set the digest for fingerprinting (defaults to the digest used when
  signing the cert). Valid values depends on your openssl and openssl ruby
  extension version.

* --debug:
  Enable full debugging.

* --help:
  Print this help message

* --verbose:
  Enable verbosity.

* --version:
  Print the puppet version number

我想抓住--argument而不是其他任何东西。

我几乎得到了这个命令,但它仍然包括":"我想排除:

puppet cert --help | egrep '^* --(.*):$' | awk '{print $2}'
--all:
--allow-dns-alt-names:
--digest:
--debug:
--help:
--verbose:
--version:

为什么'^* --(.*):$'包含":"不应该匹配'^* --'':$'之间的所有内容吗?

2 个答案:

答案 0 :(得分:4)

  

不应该匹配^* --:$之间的所有内容吗?

实际上,没有。您正在捕获一个群组,但它不会仅仅打印该群组。我建议使用-P标志来使用Perl正则表达式,并环顾四周。在您的情况下,这可能就足够了:

$ cert --help | grep -Po '^\* \K--\w+'

请注意,我还使用了-o选项,仅打印匹配的内容,而不是整行。这消除了 awk 的使用。

基于您最初的想法和更多环顾四周的更完整的一行:

$ cert --help | grep -Po '^\* \K--.*(?=:)'

编辑:正如 mklement0 的评论和精细回答中所述,这需要GNU grep。但是,您可以对Perl本身执行相同的操作,这可能已经安装在您的系统中。

$ cert --help | perl -nle 'print $1 if /^\* (--\w+)/'

这就像循环中的一行代码一样。这是由-nle自动生成的。 -n表示输入外观,-l表示自动换行符,-e表示代码行。

如果行匹配正则表达式,Perl代码行将打印第一个捕获的组。因此它也结合了原始解决方案中的想法。

要获得完整的POSIX兼容答案,请查看此页面中的answer by mklement0

答案 1 :(得分:3)

sidyll's elegant GNU grep answer提供符合POSIX标准的替代(这也解释了为什么OP的方法不起作用):

更新:Avinash Raj在评论中指出sed是一个选项,它确实允许符合POSIX标准的单一工具解决方案:sed允许我们匹配整个感兴趣的行,并用捕获组的内容(感兴趣的行的部分)替换它们:

puppet cert --help | sed -n 's/^\* \(--.*\):$/\1/p'

请注意,由于使用的sed没有 - 非标准 - -r / -E选项,因此必须使用基本正则表达式,其中()必须\ - 转义为捕获组分隔符。 功能

原始答案:

puppet cert --help | egrep '^\* --.+:$' | awk -F '\\* |:' '{print $2}'

注意:

  • ^*已替换为^\*,以确保*文字匹配,(.*)被替换使用.+,因为(a)这里的捕获组没有任何东西可以获得,并且(b)可以假设至少一个字母跟在--之后

  • -F '\\* |:'使用文字*<space>:作为字段分隔符,这可确保仅打印--...标记(第二个字段)。< / p>