sed & awk & grep

参考列表:

sed

参数解析

  • -i : 表示将改变直接写入原文件, sed默认只修改输出到终端上的内容
  • -f : -f file1 表示将sed 的操作都输出到file1
  • -n : slient模式, 默认情况下sed所有来自STDIN的数据都会输出到终端,-n只会将”来自sed的操作”输出到终端, 一般和p一起用;
  • -e : 表示使用正则匹配

example

  • 替换全部: sed “s/aaa/bbb/g” -i file
  • 每行开头插入#号: sed “s/^/#/g” -i file
  • 只在3-6行替换: sed “3,6s/aaa/bbb/g” -i file
  • 只替换每行的第1处aaa: sed “s/aaa/bbb/1” -i file
  • 只替换每行的第2处aaa: sed “s/aaa/bbb/2” -i file
  • 替换每行第3-最后一处aaa: sed “s/aaa/bbb/3,g” -i file
  • 正则: sed -e 's/^#\s*\(.*[0-9].*\)$/\1/g' filename

awk

参数解析

  • 命令格式:
    • awk [options] 'script' file_name :
    • awk [options] -f scriptfile file_name
  • [options]选项有:
    • -F : 指定分隔符. 分隔符默认是空格, awk -F"[@ /t]" 告诉awk “@符号, 空格和Tab” 都是字段分隔符. awk -F: 则表示冒号作为分隔;
    • -v : 赋值一个用户定义变量, 传递给scripts, 例 -v var=value
    • -f : 从指定文件中读取 awk scripts, 例 -f scripfile

awk脚本

基本语法

TODO

内建变量

  • NF: 表示目前的记录被分割的字段的数目,NF可以理解为 Number of Field。awk '{print FNR}' data.txt 会打印出字段个数 (默认是任何数量的空格);
  • $NF: 表示的最后一个Field(列)即输出最后一个字段的内容;
  • NR : 已经读出的记录数,即行号,从1开始;
  • $n : 表示目前的记录被分割后, 第n个字段的内容;

example 1

  • lsof | awk '{process[$1]++;} END{for(key in process) printf("%s:%d\n", key, process[key])}' #每个进程打开的文件数
  • lsof | awk '{if($8 == "TCP") opened_tcp++} END{print opened_tcp }' #打开TCP连接数量
  • lsof | awk '{opened_type[$5]++} END{ for(key in opened_type) printf("%s : %d\n", key, opened_type[key])}' #打开文件按TYPE统计

example 2

  • awk多维数组在本质上是一维数组, 因awk在存储上并不支持多维数组, awk提供了逻辑上模拟二维数组的访问方式. 例如, array[2,3] = 1这样的访问是允许的.
    awk使用一个特殊的字符串SUBSEP (\034)作为分割字段, 在上面的例子 array[2,3] = 1 中, 关联数组array存储的键值实际上是2\0343, 2和3分别为下标(2, 3), \034为SUBSEP分隔符
  • 类似一维数组的循环访问, 多维数组使用 for ( item in array ) 语法遍历数组. 与一维数组不同的是, 多维数组必须使用split()函数来访问单独的下标分量, 格式: split ( item, subscr, SUBSEP).
    例如: split (item, array2, SUBSEP); 后, array2[1]为下标“2”, array2[2]为下标“3”
# -Fb表示分隔符
awk -F '&' 'BEGIN{
# 初始化代码块
}{
# awk二维数组, 和awk外的数组变量不是一个
# 数组直接使用, 不需初始化
comment[$5, $3]++
}
END{
printf("%d", length(comment)) # awk内置数组长度
# 循环awk数组
for(ii in comment){
# 这里的ii是key, value是comment[ii]
split(ii, strs, SUBSEP) # 对多维数组的key做split操作, 得到的数组strs[1]~strs[n]是数组下标
appid = strs[1] # strs从下标1开始
user = strs[2]
printf("%d,%d\n", strs[1], strs[2], comment[ii]) >> "'$sqlLoadFile'" # 类似C的printf
}

}' $tmpDir/stat-log*.log

grep

参数解析

  • 用法: grep [参数] [查找字符串] [文件名]
  • 常用参数:
    • -n:显示匹配行及行号.
    • -c:只输出匹配行的计数.
    • -I:不区分大小写(只适用于单字符).
    • -i:不区分大小写.
    • -r:子目录递归查找.
    • -A n:a指after匹配指定行的后n行数据.
    • -B n:b 指before 匹配指定行的前N行数据.
    • -C n:显示匹配行的前后N行, 助记”center”.
    • -w xxx: 全词匹配, 比如 grep -w RUNNING, 参数w保证”RUN”不会被搜出来.

example

  • 在指定文件查找字符串: grep "XYZ" /etc/passwd
  • 在指定文件查找多个: grep -e "XYZ" -e "root" /etc/passwd
  • 在指定目录递归查找: grep -r XYZ /etc/
  • 在指定类型的文件查找字符串:
    • find . -name '*.c' -exec grep -irn "keyword" {} \;
    • find -name *.c | xargs grep -irwn "keyword"