关于linux:Linux中强大的sed和awk上

10次阅读

共计 2704 个字符,预计需要花费 7 分钟才能阅读完成。

搬运至原简书 https://www.jianshu.com/p/2ee…

最近多了很多查找编辑文件和剖析日志的需要,之前只是浅浅的晓得 sed,awk 大抵的用法,这段时间学下来才发现,sed 和 awk 真是弱小。

awk

awk 更善于对文件进行剖析和列的操作。

条件类型加动作在接文件,这里条件类型加动作为一组,一条命令中能够放多组。花括号 {} 中反对 print 的格局, if, while, for,逻辑判断等等。

$ awk '{pattern + action}' {filenames}
域编辑

例如,在咱们须要输入 test.log 的第一列:

[root@localhost ~]# awk  '{print $1}' test.log
192.29.7.26
192.29.7.14
192.26.2.26
192.15.25.26

awk 是这样操作的,读入有 ’n’ 换行符宰割的一条记录,而后将记录按指定的域分隔符划分域,填充域。$0 则示意所有域,$1 示意第一个域,$n 示意第 n 个域。默认域分隔符是 ” 空白键 ” 或 “[tab]键 ”,所以 $1 代表第一列代表 IP。
应用 -F,可指定分隔符,如:

[root@localhost ~]# awk  -F '"''{print $1}' test.log 
192.29.7.26 - - [14/Dec/2015:20:58:18 +0800] POST /praise HTTP/1.1 
192.29.7.14 - - [14/Dec/2015:20:58:19 +0800] GET /api HTTP/1.1 
192.26.2.26 - - [14/Dec/2015:20:58:19 +0800] GET /api HTTP/1.1 
192.15.25.26 - - [14/Dec/2015:20:58:19 +0800] GET /api HTTP/1.1

也可指定打印的宰割符,以下打印第一和第四列,应用 tab 排列。

[root@localhost ~]# awk '{print $1"\t"$4}' test.log 

还有很多:

[root@localhost ~]# awk '/200/' text.log     // 搜寻文件中匹配 200 字符的行
[root@localhost ~]# awk '{print NR,NF,$1,$NF}' test.log    // 显示文件 file 的以后记录号、域数和每一行的第一个和最初一个域
[root@localhost ~]# awk '/string/{print"\047 good \047"}{print $1,$2}' test.log    // 找到匹配对象 string,在其后输入特定符号,/047 代表带引号
[root@localhost ~]# awk   'BEGIN {OFS="%"} {print $1,$2}'  test.log    // 通过输入 %,扭转日志的格局
[root@localhost ~]# awk  -F ':'  'BEGIN {print"name,shell"}  {print $1","$7} END {print"blue,/bin/nosh"}'    // 能够在输出前后退出特定的标识,罕用于脚本中

合并拆分文件系列:

[root@localhost ~]awk '{print $0}' file1 file2 file3>file  // 酱 file1,file2,file3 合并成 file

awk 无需在变量前增加 $ 符号,这是与 shell 不一样的中央,下面的例子用到一些变量,在 awk 中长于使用变量会使工具用处大大增加。以下为各变量的含意。

ARGC        命令行变元个数 
ARGV        命令行变元数组 
FILENAME    以后输出文件名 
FNR     以后文件中的记录号 
FS     输出域分隔符,默认为一个空格 
RS     输出记录分隔符 
NF     以后记录里域个数 
NR     到目前为止记录数 
OFS     输入域分隔符 
ORS     输入记录分隔符 
数组与自定义变量

除了 awk 的内置变量,awk 还能够自定义变量。

[root@localhost ~]#  awk '{count++;print $1;} END{print count}' test.log 
192.29.7.26
192.29.7.14
192.26.2.26
192.15.25.26
4

比方刘老师说想看,每分钟的申请数,以下能够将每分钟的申请数列出:

[root@localhost ~]# awk -F: '{count[$2":"$3]++} END {for (minute in count) print minute, count[minute]}' test.log 
20:58 4

应用数组能够将日志中 IP 的申请数统计进去

[root@localhost ~]# awk '{a[$1]+=1;}END{for(i in a){print a[i]" "i;}}' test.log
复合表达式

能够应用 && 或 || 连贯多个表达式,表达式用 () 扩起
(expr1) && (expr2)
(expr1) ||(expr)

比方须要查看日志中某一时间断的申请数:

awk '$4>="[01/Dec/2015:15:00:00"&&$4<="[01/Dec/2015:22:00:00"' test.log
IF

和 C 语言一样,根本格局是这样的

if (expression1) {action1} else if (expression2) {action2} else {action3}

来个栗子????
有如下文本,要求:将第一列中反复的合并为一行,其第二列填入最长地址的那列

0001|hi
0002|dog
0001|It’s a good day
0003|cat
0001|nice
0004|linux

失去的后果应为:

0001|It’s a good day
0002|dog
0003|cat
0004|linux

代码:

#!/bash/bin
BEGIN{FS=OFS="|"; i=1;}
{if(a[$1]==0){b[i]=$1;a[$1]=$2;i++}
if(length(a[$1])}
END{for(j=1;j}

比拟代码:(实现不全)

awk 'BEGIN{FS=OFS="|"} !(length(a[$1])>length($2)){a[$1]=$2} END{for(i in a)print i,a[i]}' data.txt

解释:此例中,用了两个数组,a 用来与 $1 关联,b 用来程序记录,使得在最初打印时是齐全依照 $1 程序打印。条件句首先判断数组元素是否是第一次写入,若非,则比拟以后 $2 值和以前贮存的值长度。
性能不全代码不能程序打印。当 $1 有反复,而 $2 长度第一次、第二次、第三次是以递加的形式时,该代码利用得较好。然而,当 $2 各次失去的长度不确定时,代码不能实现上述性能。例如:本例中第 5 行的第二列若比第 3 行的第二列长度长时,性能不全代码就不能实现要求。

正文完
 0