可以改用awk吗?


17

我想从中获取数字rating作为输出

# nc localhost 9571 
language:
language:en_ZA.UTF-8
language:en_ZW.UTF-8
session-with-name:Ubuntu Classic (No effects):gnome-session --session=2d-gnome
session-with-name:Ubuntu (Safe Mode):gnome-session -f --session=2d-gnome
session-with-name:Ubuntu Classic:gnome-session --session=classic-gnome
xsession:/etc/X11/Xsession
rating:94

我可以这样

# nc localhost 9571 | grep rating | cut -d: -f2
94

但是可以awk用来代替一个更简单的解决方案吗?


这个问题似乎是题外话,因为它是关于awk的界面编程,更相关的StackOverflow.com
麦哲伦

Answers:


32
$ nc localhost 9571 | awk -F: '/rating/ { print $2 }'

7
如果任何字段值或名称包含字符串“ rating”,即其中一个会话名称中包含单词“ rating”,则可能给出错误的结果。更好:awk -F: '$1 == "rating" {print $2}'
Ingmar Hupp

3
也许awk -F: '/^rating:/ { print $2 }'呢?
CVn

我知道,但是我是根据OP的命令进行转换的。
量子

@IngmarHupp我以为完全一样。实际上,匹配有问题的确切记录要好得多,我已经用此更改编辑了答案。希望这将帮助人们学习更有效地使用awk。
Dan Molding

14

Quanta击败了我,但sed如果您有这种倾向,我将提供一个变体:

nc localhost 9571 | sed -ne 's/^rating://p'

就像疯子说的一样。您当前的解决方案是完美的。(尽管我会grep "^rating:"而不是grep 来确保您只得到想要的行。)


我爱sed!它是如此的未被充分利用和低估……
Mei

9

您也可以只使用shell:

nc localhost 9571 | 
while IFS=: read key val; do [[ $key = "rating" ]] && echo "$val"; done

这是最快的方法-防止产生超出的任何进程nc。真好!

7

是的,您可以(并且应该)使用(一个)awk代替(两个)grep并剪切:

$ nc localhost 9571 | awk -F: '/^rating:/ { print $2 }'

确保尽可能匹配您的行,以避免出现难看的错误。

  • /rating/ 作品,
  • /^rating/ 更好(更安全),
  • /^rating:/ 最好(在这种情况下)。

4

它可以:

nc localhost 9571  | awk -F: '{ if ($1 == "rating") print $2 }' 

(我不知道您在使用上面的本地主机做什么,因此将您的输出用作我的awk命令的输入,然后将“ cat”替换为“ nc ...”-但这应该没问题。)

但是,为什么要这样做呢? UNIX的方式是拥有许多小型工具,每个小型工具都可以通过管道将它们串在一起,而不是使用大型多功能工具。您需要选择一条匹配行,然后从中选择一个字段:grep选择具有匹配项的行,然后cut从输入行中选择字段;他们是完成任务的完美选择。但是,如果您确实确实想用awk进行全过程,那么就可以了。


原因之一是使用grepcut需要产生两个进程,而使用awk(或sed)仅需要一个。产生一个进程在计算上是昂贵的。此外,与使用perlruby(等人),sedawk是更轻便前面。

2
公平地说,尽管我注意到我的(F15)系统上awk二进制文件的大小为360948字节,而grep和cut二进制文件的总大小为170824字节。因此,只有一个fork + exec的周期更少,但是更多的内存和更多的IO从光盘中获取二进制文件。老实说,我怀疑这些考虑因素是否对现代系统很重要,但是如果您想将其最小化,那您就走了!
MadHatter

Foo Bah:感谢您的编辑建议,但Quanta的帖子比我的晚,比您的建议更精简。我之所以选择我的,是因为入门级awk用户更容易看到它的工作原理,因此拒绝了您的编辑。谢谢您的想法!
MadHatter

3

虽然Quanta的答案是最简单的,我也想写一个答案,但是我敢打赌,您不知道GNU awk(gawk)也可以进行网络连接吗?如果您确实需要,可以使用awk编写整个内容:

BEGIN {
    FS = ":"
    f = "/inet/tcp/0/127.0.0.1/9571"
    while ((f |& getline) > 0)
        if ($1 ~ /^rating$/) {print $2}
}

如果服务器未安装nc或nc限制了权限,或者您真的很喜欢awk,则这可能很有用。


哦 真好 网络协同处理示例。
Edward Morbius博士2012年

0

您也可以使用sed

nc localhost 9571 | sed -n "s/^rating:\([\d]*\)/\1/p"

这将确保“ rating”开始行,并且数字跟随 rating:


0

如果选择Perl:

nc localhost 9571 | perl -F: -lane 'print $F[1] if /rating/'

-aautosplits各行成@F阵列
-F:用途:作为字段分隔符,而不是空白的缺省
/rating/如果为真正则表达式被发现返回
$F[1]是的第二元件@F阵列。
Perl数组以元素0开头,而awk以$ 1开头

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.