You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关于sed命令执行逻辑、awk用法及Bash数组判断的技术咨询

Nginx日志统计Bash脚本疑问解答

1. sed命令sed 's/.*\[//g;s/].*//g;s/:.*//g'处理过程

这条sed命令包含三个连续的替换操作,针对每行Nginx日志分步处理:

  • 第一步:s/.*\[//g:匹配从行首到左方括号[的所有内容(包括[),将其替换为空。以日志第一行为例,处理后得到16/Feb/2020:22:31:32 +0000]。
  • 第二步:s/].*//g:匹配右方括号]及后面的所有内容,替换为空。处理后得到16/Feb/2020:22:31:32 +0000。
  • 第三步:s/:.*//g:匹配第一个冒号:及后面的所有内容,替换为空。最终提取出日期部分16/Feb/2020。

2. awk '{print $1}'的作用

awk默认以空白字符(空格、制表符)为分隔符拆分每行内容,$1代表拆分后的第一个字段。在给定的Nginx日志格式中,每行第一个字段就是发起请求的客户端IP地址,所以这个命令的作用就是提取日志中的客户端IP。

3. if [[ -v day_array[$day] ]]的测试内容

-v是Bash的条件测试运算符,用于检查关联数组中指定键的元素是否存在。这条语句的作用是:测试关联数组day_array中是否已经存在以变量$day(即提取出的日期)为键的元素。如果存在,就将该元素的值加1(统计该日期的请求次数);如果不存在,就初始化该键对应的值为1,实现按天统计请求量的功能。

关于在线测试sed命令时无法读取文件的问题

你使用的在线sed工具仅支持直接输入文本内容进行测试,不支持读取本地文件。解决方法是将日志内容复制粘贴到工具的输入框中,再执行sed命令即可完成测试。


原始日志输入

172.19.0.100 - - [16/Feb/2020:22:31:32 +0000] "GET /site HTTP/1.1" 200 36565 "https://command-not-found.com/curl" "Mozilla/5.0+(compatible; UptimeRobot/2.0; http://www.uptimerobot.com/)" "172.19.0.3"
172.19.0.101 - - [16/Feb/2020:22:30:10 +0000] "GET /credits HTTP/1.1" 200 31067 "-" "Mozilla/5.0 (compatible; YandexBot/3.0; +http://yandex.com/bots)" "172.19.0.2"
172.19.0.102 - - [17/Feb/2020:22:30:10 +0000] "GET /index HTTP/1.1" 200 31067 "-" "Mozilla/5.0 (compatible; YandexBot/3.0; +http://yandex.com/bots)" "172.19.0.2"
172.19.0.100 - - [18/Feb/2020:22:35:10 +0000] "GET /index HTTP/1.1" 200 31067 "-" "Mozilla/5.0 (compatible; YandexBot/3.0; +http://yandex.com/bots)" "172.19.0.2"

原始Bash脚本

#!/usr/bin/env bash
LOG_FILE="$1"

function request_per_day() {
    declare -A day_array
    while read line; do
        day=$(echo "$line" | sed 's/.*\[//g;s/].*//g;s/:.*//g')
        if [[ -v day_array[$day] ]]; then
            day_array[$day]=$((day_array[$day]+1))
        else
            day_array[$day]=1
        fi
    done < $LOG_FILE

    for day in ${!day_array[@]}; do echo ${day_array[$day]} $day; done | sort -rn | head -10
}

function request_per_ip() {
    declare -A ip_array
    while read line; do
        ip=$(echo $line | awk '{print $1}')
        if [[ -v ip_array[$ip] ]]; then
            ip_array[$ip]=$((ip_array[$ip]+1))
        else
            ip_array[$ip]=1
        fi
    done < $LOG_FILE

    for ip in ${!ip_array[@]}; do echo ${ip_array[$ip]} $ip; done | sort -rn | head -10
}

request_per_day
echo ""
request_per_ip

内容的提问来源于stack exchange,提问作者Gifter Villanueva

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 21:30:31