1. 排序+统计
sort | uniq -c
注意 uniq -c 只能统计临近的重复行,因此需要 sort
2. grep
- -v 排除
- -E 正则
3. awk
3.1 NF 与循环
NF 是 awk 语法内置变量,代表 field 的个数。 可以配合循环使用,例如:
echo "a bb ccc" | awk '{ for (i=1; i<=NF; i++) print $i}'
会输出
a
bb
ccc
3.2 指定分割符
-F 指定分割 field 的符号。例如:
echo "a&bb&ccc" | awk -F '&' '{ for (i=1; i<=NF; i++) print $i}'
3.3 提取指定值并计算平均
假设某文件里包含了一些 log,都含有 "xxms," 的格式。则:
cat 1.log | awk '{ total += $NF; count++ } END { if (count > 0) print "Average:", total/count, "ms"; }' RS="ms,"
一些要点:
$NF: 这个写法活用了 3.1 节提到的NF,NF代表 field 个数,因此$NF代表每行最后一个 field 的值RS="ms,":RS指定分隔 record 的符号。默认情况下RS是换行符。在本节的场景中,在指定分隔符为ms,后,则可以直接使用$NF直接获取我们想要的数值,是一种取巧的方案。
3.4 NR
用于每一行处理,和 END 块中。
在逐行处理时,代表当前行数,从 1 开始;在 END 块中,为文件的行数。
非常适合用于数组的赋值。例如,假设我们有一系列耗时数据,现在需要提取出其中的 p95,则可以在 sort 之后使用:
{ data[NR] = $NF }
END {
i = int(NR * 0.95);
print "p95 is", data[i];
}
4. sed
4.1 字符替换
例如把 orange 替换为 apple,那么:
echo "I love orange" | sed 's/orange/apple/g'
其中:
/: 是 sed 的语法分隔符,分成了s、orange、apple、g四个部分s: 指进行替换操作,s is short for substituteorange/apple: 替换对象和需要替换为的值g: 全局替换,g for global。如果不带g,则只会替换第一次出现的 orange
可以把替换值设为空,从而从字符流中删除掉某个词。例如需要处理转义字符时,如果情况允许,我们可以粗暴地将所有 \ 删除,即:
echo '{name: alice}' | sed 's/\\//g'
4.2 进阶用法之匹配与提取
在匹配规则中可以使用正则表达式。在替换对象中可以使用 \1 来输出第 1 个匹配项。
例如,我们有这样的一些数据:
"Alice": 1
"Bob": 2
则我们可以使用 sed 's/^"\([^"]*\).*/\1/' 来提取出其中的 Alice 和 Bob,且移除掉不必要的引号。
4.3 输出特定行数
输出第 100 ~ 200 行,不做任何替换:
sed -n '100,200p' my_app.log
其中 -n 代表禁用默认的每行都输出的行为。
p 是 print 子命令
只输出第 100 行,并且进行替换等:
sed -n '100{s/WARN/WARNING/g; p;}' my_app.log
5. xargs
5.1 基础用法
-d 指定分隔符,-n 指定一行展示的个数
实现一行转多行。
echo '1,2,3' | xargs -d, -n1
结果是:
1
2
3
5.2 指定占位符并替换
-I 指定占位符,常用的是 {}。
例如,将下列文件都移动走:
find ./foo -type f -name "*.txt" | xargs -I {} mv {} ./bar/
5.3 并发执行
-P (max-procs) 参数,可以并发执行命令。
例如,如果我想同时起好几个 curl ,可以这么干:
seq 10 | xargs -P 10 -I {} curl https://www.a.com
注意这里 -I 制定的占位符其实并没有被用到,但是 -I 隐含了 -L 1(每次只处理一行)。如果没有 -I, xargs 会尝试把 seq 的输出当做参数扔给 curl,即 curl https://www.a.com/api 1 2 3 4 5 6 7 8 9 10
TODO: 一些题目:
- 移除掉前导、后导的多余的引号
