【问题标题】:How to print a series of words using awk?如何使用awk打印一系列单词?
【发布时间】:2014-05-20 17:02:48
【问题描述】:

我知道awk 可用于仅打印输出中的某些单词。例如

dpkg -l|awk '{print $2}'

将从dpkg -l 的输出中打印第二个单词。

我想要做的是,在给定单词之后打印每个单词。我的命令看起来像这样

awk '{printf "%-40s %s\n", $1, $n}'

我不想打印带有$n$0 的所有单词,而是想打印后面的每个单词,比如第5 个字符。

我该怎么做?

编辑:我的完整命令是

bind -P|grep "can be found"|sort|awk '{printf "%-40s %s\n", $1, $n}'

这给出了类似的输出

abort                                    abort can be found on "\C-g", "\C-x\C-g", "\e\C-g".
accept-line                              accept-line can be found on "\C-j", "\C-m".
backward-char                            backward-char can be found on "\C-b", "\eOD", "\e[D".
backward-delete-char                     backward-delete-char can be found on "\C-h", "\C-?".

character-search-backward                character-search-backward can be found on "\e\C-]".
character-search                         character-search can be found on "\C-]".
clear-screen                             clear-screen can be found on "\C-l".

还有更多的行。 “可以在中找到中止”和类似的行无关紧要,我不想要它们,但我想要这 5 个字符之后的所有内容。

所以输出应该是这样的

abort                                    "\C-g", "\C-x\C-g", "\e\C-g".
accept-line                              "\C-j", "\C-m".
backward-char                            "\C-b", "\eOD", "\e[D".
backward-delete-char                     "\C-h", "\C-?".

如何使用 awk 或任何其他命令来做到这一点?我需要保留列输出。

【问题讨论】:

  • 喜欢这个many-piped-commands | sed -n 's/myword/&\n/;s/.*\n//p'?
  • 你能举个例子吗?什么是单词
  • @devnull 我在新编辑中发布了一个命令作为示例。
  • @Jayesh 我添加了一个命令作为示例。请在编辑中查看。

标签: bash awk text-processing


【解决方案1】:

试试下面:

 many commands | awk '{for(i=6;i<=NF;i++){printf "%s\n", $i}}'

如果您不想在下面使用换行符分隔每个单词,则将从字段 6 开始打印所有内容:

many commands | awk '{for(i=6;i<=NF;i++){printf "%s ", $i}}'

编辑:

对于您的完整问题,请使用以下内容:

 bind -P|grep "can be found"|sort | awk '{printf "%-40s", $1} {for(i=6;i<=NF;i++){printf "%s ", $i}{printf"\n"}}'

给出输出:

abort                                   "\C-g", "\C-x\C-g", "\e\C-g".
accept-line                             "\C-j", "\C-m".
backward-char                           "\C-b", "\eOD", "\e[D".
backward-delete-char                    "\C-h", "\C-?".
backward-kill-line                      "\C-x\C-?".
etc...

【讨论】:

  • 这用新行分隔单词。
【解决方案2】:

在这种情况下使用更好的工具,例如 perl:

perl -lne 'print $1 if(/\b(myword .*)/)'

不完全确定您在寻找什么。但这会删除该行中的前 5 个单词:

awk '{for(i=6;i<=NF;i++){printf $i" "}print ""}'

Tested

【讨论】:

  • 感谢您的回复。您可以根据我的编辑使其相关吗?再次感谢
  • 我添加了一个命令和预期的输出,请看一下。
【解决方案3】:

如果您需要显式使用 AWK,您可以尝试以下方法:

awk '{ if( match($0,"^.{5}[^[:space:]]*[[:space:]]([^[:space:]]+)(:?$|[[:space:]])", arr) ) {print arr[1]}}'

match 函数确保在开始捕获单词之前至少有 5 个字符(空白和字母数字)。如果第五个字符之后的下一个元素是单词的中间,它会忽略它并转到下一个完整的单词并捕获它。 arr 中的第一个位置对应于正则表达式中捕获的元素,即第五个字符之后的第一个完整单词。

【讨论】:

  • 这个命令给出了一个语法错误。我在我的问题中添加了一个示例命令。请看一看。
【解决方案4】:

保存第一个字段。作为条件/模式,尝试用空字符串替换 ".*can be found on "。如果发生替换,则打印保存的第一个字段以及 $0 剩下的任何内容。

bind -P | awk '{ first = $1 } sub(/.*can be found on /, "") { printf "%-40s%s\n", first, $0 }

在您的原始版本中:

bind -P|grep "可以找到"|sort|awk '{printf "%-40s %s\n", $1, $n}' $n 中的 n 计算结果为 0,因此 awk 会打印第一个单词和整个记录。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-09-14
    • 1970-01-01
    • 2021-09-29
    • 1970-01-01
    • 1970-01-01
    • 2023-03-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多