Data Wrangling 以下代码可以查看服务器的日志
需要注意的是 myserver
由,<用户名>@<$ip$地址构成>
sed
是一种匹配工具,s
命令的形式如下:s/REGEX/SUBSTITUTION/
其中 REGEX
是正则表达式,而SUBSTITUTION
是替代文本,也就是将匹配到的正则表达式转换为代替文本,默认只替代一遍。在后面加上g
可以多次匹配。
为了支持更不用加上\
我们需要在sed
后加上-E
以下是该命令的一些示例用法:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 rust@DESKTOP-L4PLVQ4:~$ echo 'aba' | sed 's/[ab]//' ba rust@DESKTOP-L4PLVQ4:~$ echo 'bba' | sed 's/[ab]//' ba rust@DESKTOP-L4PLVQ4:~$ echo 'bba' | sed 's/[ab]//g' rust@DESKTOP-L4PLVQ4:~$ echo 'bbac' | sed 's/[ab]//g' c rust@DESKTOP-L4PLVQ4:~$ echo 'bcbzac' | sed 's/[ab]//g' czc rust@DESKTOP-L4PLVQ4:~$ echo 'abcaba' | sed -E 's/(ab)*//g' ca rust@DESKTOP-L4PLVQ4:~$ echo 'abcaba' | sed 's/\(ab\)*//g' ca rust@DESKTOP-L4PLVQ4:~$ echo 'abcabbc' | sed -E 's/(ab|bc)*//g' c
先把有关 Disconnected from
的日志文件都过滤出来。
1 2 3 sudo ssh ubuntu@101.35.*.* 'journalctl | grep ssh | grep "Disconnected from"'> ssh.log
以下命令可以将Disconnected from
全部替换为空行。
1 2 cat ssh.log | sed 's/.*Disconnected from//'
以下命令可以将整行进行替换。
1 2 3 cat ssh.log | sed -E 's/^.*Disconnected from (invalid |authenticating )?(user .* )?[0-9.]+ port [0-9]+( \[preauth\])?$//' | head -n70
被圆括号内的正则表达式匹配到的文本,都会被存入一系列以编号区分的捕获组中。捕获组的内容可以在替换字符串时使用(有些正则表达式的引擎甚至支持替换表达式本身),例如\1
、 \2
、\3
等等.
因此以下命令可以只保留用户名
1 2 3 cat ssh.log | sed -E 's/^.*Disconnected from (invalid |authenticating )?user (.*) [0-9.]+ port [0-9]+( \[preauth\])?$/\2/' | head -n70
以下命令可以将查找结果排序:
1 2 3 cat ssh.log | sed -E 's/^.*Disconnected from (invalid |authenticating )?user (.*) [0-9.]+ port [0-9]+( \[preauth\])?$/\2/' | sort
以下代码可以去重并计数:
1 2 3 4 cat ssh.log | sed -E 's/^.*Disconnected from (invalid |authenticating )?user (.*) [0-9.]+ port [0-9]+( \[preauth\])?$/\2/' | sort | uniq -c
以下代码可以查看有多少行:
1 2 3 4 5 cat ssh.log | sed -E 's/^.*Disconnected from (invalid |authenticating )?user (.*) [0-9.]+ port [0-9]+( \[preauth\])?$/\2/' | sort | uniq -c | wc -l
以下代码可以查看十个最多的用户名:
1 2 3 4 5 6 cat ssh.log | sed -E 's/^.*Disconnected from (invalid |authenticating )?user (.*) [0-9.]+ port [0-9]+( \[preauth\])?$/\2/' | sort | uniq -c | sort -nk1,1 | tail -n10
sort -n
会按照数字顺序对输入进行排序(默认情况下是按照字典序排序 -k1,1
则表示“仅基于以空格分割的第一列进行排序”。,n
部分表示“仅排序到第n个部分”,默认情况是到行尾。就本例来说,针对整个行进行排序也没有任何问题,我们这里主要是为了学习这一用法!
awk
可以以列为对象操作数据,而paste -s
可以将内容粘贴进一行,d,
可以将一行中的数据用间隔符‘,’
分开
1 2 3 4 5 6 7 8 cat ssh.log | sed -E 's/^.*Disconnected from (invalid |authenticating )?user (.*) [0-9.]+ port [0-9]+( \[preauth\])?$/\2/' | sort | uniq -c | sort -nk1,1 | tail -n20 | awk '{print $2}' | paste -sd,
以下命令可以找出只出现一次并且以c
开头以c
结尾的用户名
1 2 3 4 5 6 7 cat ssh.log | sed -E 's/^.*Disconnected from (invalid |authenticating )?user (.*) [0-9.]+ port [0-9]+( \[preauth\])?$/\2/' | sort | uniq -c | sort -nk1,1 | awk '$1 == 1 && $2 ~ /^c.*c$/ {print $0}' 1 contec
以下两条命令可以起到同样的效果
1 2 3 4 5 6 7 cat ssh.log | sed -E 's/^.*Disconnected from (invalid |authenticating )?user (.*) [0-9.]+ port [0-9]+( \[preauth\])?$/\2/' | sort | uniq -c | sort -nk1,1 | awk '$1 == 1 && $2 ~ /^c.*c$/ {print $0}' | wc -l
1 2 3 4 5 6 7 8 cat ssh.log | sed -E 's/^.*Disconnected from (invalid |authenticating )?user (.*) [0-9.]+ port [0-9]+( \[preauth\])?$/\2/' | sort | uniq -c | sort -nk1,1 | awk 'BEGIN {rows = 0 } $ 1 == 1 && $2 ~ /^c.*c$/ {rows += 1} END { print rows }'
BEGIN
也是一种模式,它会匹配输入的开头( END
则匹配结尾)。然后,对每一行第一个部分进行累加,最后将结果输出。
事实上,我们完全可以抛弃 grep
和 sed
,因为 awk
就可以解决所有问题 。但是这样会十分painful
bc可以对字符串进行数值计算。
1 2 3 4 5 6 7 8 cat ssh.log | sed -E 's/^.*Disconnected from (invalid |authenticating )?user (.*) [0-9.]+ port [0-9]+( \[preauth\])?$/\2/' | sort | uniq -c | sort -nk1,1 | awk '$1 != 1 { print $1 }' | paste -sd+ | bc -l
以上代码可以将数量不是1
的用户数相加,先把它们打印到一行用 +
分隔,最后用bc
相加。
可以用R语言对数据进行处理
1 2 3 4 5 6 7 8 9 cat ssh.log | sed -E 's/^.*Disconnected from (invalid |authenticating )?user (.*) [0-9.]+ port [0-9]+( \[preauth\])?$/\2/' | sort | uniq -c | sort -nk1,1 | awk '$1 != 1 { print $1 }' | R --slave -e 'x <- scan(file="stdin", quiet=TRUE); summary(x)' Min. 1st Qu. Median Mean 3rd Qu. Max. 2.00 3.00 5.00 68.68 9.00 8121.00
也可以用gunplot
进行绘图,但是bash好像不支持gnuplot
1 2 3 4 5 6 7 8 9 cat ssh.log | sed -E 's/^.*Disconnected from (invalid |authenticating )?user (.*) [0-9.]+ port [0-9]+( \[preauth\])?$/\2/' | sort | uniq -c | sort -nk1,1 | awk '$1 != 1 { print $1 }' | tail -n10 | gnuplot -p -e 'set boxwidth 0.5; plot "-" using 1:xtic(2) with boxes'