我在bash脚本中有一行,用于计算特定页面的唯一IP请求总和。
grep $YESTERDAY $ACCESSLOG | grep "$1" | awk -F" - " '{print $1}' | sort | uniq -c | awk '{sum += 1; print } END { print " ", sum, "total"}'
我试图将sum的值加到awk语句之外的变量中,这样我就可以将页面相互比较。到目前为止,我尝试过各种类似的组合:
unique_sum=0
grep $YESTERDAY $ACCESSLOG | grep "$1" | awk -F" - " '{print $1}' | sort | uniq -c | awk '{sum += 1; print ; $unique_sum=sum} END { print " ", sum, "total"}'
echo "${unique_sum}"
这导致" 0"的回声。我已尝试将__$unique_sum=sum__
放入END
,初始化变量(awk -v unique_sum=0 ...
)的各种组合以及将变量赋值置于引用部分之外。
到目前为止,我的Google-fu失败可怕,因为大多数人只是将整个输出发送到变量。在此示例中,除了总数之外,还打印了许多行(每个IP一行)。没有办法捕获总和'变量,有没有办法捕获最后一行输出?
这可能是我在awk中尝试过的最复杂的事情之一,所以我对自己做过任何有用的事情的信心非常低。任何帮助将不胜感激!
答案 0 :(得分:2)
您无法在awk程序中分配shell变量。通常,没有子进程可以改变其父进程的环境。你必须让awk程序打印出计算出的值,然后shell可以获取该值并将其分配给变量:
output=$( grep $YESTERDAY $ACCESSLOG | grep "$1" | awk -F" - " '{print $1}' | sort | uniq -c | awk '{sum += 1; print } END {print sum}' )
unique_sum=$( sed -n '$p' <<< "$output" ) # grab the last line of the output
sed '$d' <<< "$output" # print the output except for the last line
echo " $unique_sum total"
该管道可以简化很多:awk可以做grep可以做的事情,所以首先
grep $YESTERDAY $ACCESSLOG | grep "$1" | awk -F" - " '{print $1}'
是(更长,但只有一个过程)
awk -F" - " -v date="$YESTERDAY" -v patt="$1" '$0 ~ date && $0 ~ patt {print $1}' "$ACCESSLOG"
最后一个awk程序只计算了多少行,可以用wc -l
所有在一起:
unique_output=$(
awk -F" - " -v date="$YESTERDAY" -v patt="$1" '
$0 ~ date && $0 ~ patt {print $1}
' "$ACCESSLOG" | sort | uniq -c
)
echo "$unique_output"
unique_sum=$( wc -l <<< "$unique_output" )
echo " $unique_sum total"