【问题标题】:How do I print a range of data in awk?如何在 awk 中打印一系列数据?
【发布时间】:2012-09-14 04:38:03
【问题描述】:

我正在查看我的 access_logs 并使用如下语句:

cat access_log | grep 16/Sep/2012:17 | awk '{print $12 $13 $14 $15 $16}' | sort | uniq -c | sort -n | tail -40

目的是查看过去一小时内访问我的服务器的任何人的用户代理,按点击次数排序。我的服务器有异常活动,我想阻止任何不需要的蜘蛛/等。

但部分:awk '{print $12 $13 $14 $15 $16}' 会更受欢迎,例如:awk '{print $12-through-end-of-line}',这样我就可以看到每个用户代理的长度不同。

有没有办法用 awk 做到这一点?

【问题讨论】:

    标签: apache bash awk centos


    【解决方案1】:

    不是很优雅,但这很有效:

    grep 16/Sep/2012:17 access_log | awk '{for (i=12;i<=NF;++i) printf "%s ",$i;print ""}'
    

    它的副作用是将字段之间的多个空格压缩为一个,并在行尾放置一个额外的空格,但这可能并不重要。

    【讨论】:

    • 这也比我的回答有好处,即允许您通过在awk 脚本中移动搜索文本来消除grepawk '/16\/Sep\/2012:17/ { ... }' access_log
    【解决方案2】:

    我从来没有找到过;在这种情况下,我使用cut(假设我不需要awk的灵活处理字段分隔):

    # Assuming tab-separated fields, cut's default
    grep 16/Sep/2012:17 access_log | cut -f12- | sort | uniq -c | sort -n | tail -40
    
    # For space-separated fields (single spaces, not arbitrary amounts of whitespace)
    grep 16/Sep/2012:17 access_log | cut -d' ' -f12- | sort | uniq -c | sort -n | tail -40
    

    (澄清:我从来没有找到一个的方法。我在必要时使用了@twalberg的for循环,但如果可能的话,我更喜欢使用cut。)

    【讨论】:

    • 难道不是 cut -f12- 得到所有东西 awk '{print $12-through-end-of-line}',根据 O.P. Dang,忘记了 cut。很好的解决方案!
    • 好点。我从字面上理解了 12-16,但cut -f12- 更适合获得整个其余部分。
    • 似乎是空格分隔而不是制表符分隔。我喜欢这个主意,但没有奏效。
    • @danielson317 我已经更新了我的答案,但只有在每个字段之间只有一个空格时才会起作用。 awk 更灵活,因为它考虑了任意数量的空格(由空格、制表符等组成)来分隔两个字段。
    • 优秀。我已经将另一个标记为解决方案,因为它使用了 awk 但我投了你的票。
    【解决方案3】:
    $ echo somefields:; cat somefields ; echo from-to.awk: ; \
      cat from-to.awk ; echo ;awk -f from-to.awk  somefields 
    somefields:
    a b c d e f g h i j k l m n o p q r s t u v w x y z
    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
    from-to.awk:
    { for (i=12; i<=NF; i++) { printf "%s ", $i }; print "" }
    
    l m n o p q r s t u v w x y z 
    12 13 14 15 16 17 18 19 20 21 
    

    来自男人 awk:

    NF 当前输入记录的字段数。


    所以你基本上循环遍历从 12 到最后一个的字段(用空格分隔)。

    【讨论】:

    • 不确定我是否理解。不过感谢您的回复。
    • 文件 awk 读取的每一行(或从另一个命令如 grep 的输出)都是一条记录。 NF 是每一行的“字段”数。在上面的示例中,字母表有 26 个字段,数字行有 21 个字段,文件包含 2 条记录。
    【解决方案4】:

    为什么不

      #!/bin/bash
      awk "/$1/"'{for (i=12;i<=NF;i++) printf("%s ", $i) ;printf "\n"}' log | sort | uniq -c | sort -n | tail -40 
    

    在脚本文件中。

    那么你可以这样称呼它

     myMonitor.sh 16/Sep/2012:17
    

    没有办法测试这个权利。对任何格式/语法错误的道歉。 希望你能明白。

    IHTH

    【讨论】:

    • 剧本的好主意。我并没有真正做到这一点,以证明目前必须设置所有这些是合理的。不过还是谢谢。
    【解决方案5】:
    awk '/16/Sep/2012:17/{for(i=1;i<12;i++){$i="";}print}' access_log| sort | uniq -c | sort -n | tail -40
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-05-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多