1 awk:文本和数据处理工具
awk擅长于对数据进行分析并生成报告,简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各种分析处理。
使用方法:awk '{pattern + action}' {filenames}
其中pattern 表示awk 在数据中查找的内容,而action是在找到匹配内容时所执行的一系列命令。花括号({})不需要在程序中始终出现,但它们用于根据特定的模式对一系列指令进行分组。pattern就是要表示的正则表达式,用斜杠括起来。准备实例操作文件:netstat -t >> netstat.txt
1.1 打印输出:print,格式化打印输出:printf
awk '{print$1, $4}' netstat.txt
awk '{printf "%-8s %-8s %-8s %-18s %-22s %-15s\n",$1,$2,$3,$4,$5,$6}' netstat.txt
1.2 过滤记录:awk '$3==0 && $6=="LISTEN"' netstat.txt
其中的“==”为比较运算符。其他比较运算符:!=,>, <, >=, <=
awk '$3>0 {print $0}' netstat.txt
加入表头:内建变量NR
awk '$3==0 && $6=="LISTEN" || NR==1 ' netstat.txt
再加上格式化输出
awk '$3 ==0 && $6=="LISTEN" || NR==1 {printf "%-20s %-20s %s\n",$4,$5,$6}' netstat.txt
ps:awk的内建变量
$0 |
当前记录(这个变量中存放着整个行的内容) |
$1~$n |
当前记录的第n个字段,字段间由FS分隔 |
FS |
输入字段分隔符默认是空格或Tab |
NF |
当前记录中的字段个数,就是有多少列 |
NR |
已经读出的记录数,就是行号,从1开始,如果有多个文件话,这个值也是不断累加中。 |
FNR |
当前记录数,与NR不同的是,这个值会是各个文件自己的行号 |
RS |
输入的记录分隔符,默认为换行符 |
OFS |
输出字段分隔符,默认也是空格 |
ORS |
输出的记录分隔符,默认为换行符 |
FILENAME |
当前输入文件的名字 |
输出行号:awk '$3 ==0 && $6=="ESTABLISHED"|| NR==1 {printf "%02s %s %-20s %-20s %s\n",NR, FNR,$4,$5,$6}' netstat.txt
指定分隔符:awk 'BEGIN{FS=":"} {print $1,$3,$6}' /etc/passwd
或者awk -F: '{print $1,$3,$6}' /etc/passwd
以\t作为分隔符输出:awk -F: '{print $1,$3,$6}' OFS="\t" /etc/passwd
1.3 字符串匹配:~表示匹配模式开始,正则表达式匹配。
awk '$6 ~ /TIME/ || NR ==1 {print NR,$4,$5,$6}' OFS="\t" netstat.txt
awk '$6 ~ /ESTABLISHED/ || NR==1 {print NR,$4,$5,$6}' OFS="\t" netstat.txt
awk '/LISTEN/' netstat.txt
使用“/TIME|ESTABLISHED/” 来匹配TIME 或者ESTABLISHED :
awk '$6 ~ /FIN|TIME/ || NR==1 {print NR,$4,$5,$6}' OFS="\t" netstat.txt
模式取反:!~
awk '$6 !~ /TIME/ || NR==1 {print NR,$4,$5,$6}' OFS="\t" netstat.txt
或者awk '!/WAIT/' netstat.txt
1.4 拆分文件:使用数据流重定向”>”
awk 'NR!=1 {print > $6}' netstat.txt NR!=1表示不处理表头
把指定的列输出到文件: awk 'NR!=1{print $4,$5 > $6}' netstat.txt
使用程序流进行条件拆分:if else
awk 'NR!=1{if($6 ~ /TIME|ESTABLISHED/) print > "1.txt";
else if($6 ~ /LISTEN/) print > "2.txt";
else print > "3.txt"}' netstat.txt
1.5 统计
计算所有的C文件,CPP文件和H文件的文件大小总和:
ls -l *.cpp *.c*.h | awk '{sum+=$5} END {print sum}'
统计各个connection状态的用法:使用数组
awk 'NR!=1{a[$6]++;} END {for (i in a) print i ", " a[i];}' netstat.txt
统计每个用户的进程的占了多少内存:
ps aux| awk 'NR!=1{a[$1]+=$6;} END { for(i ina) print i ", " a[i]"KB";}'
数组:因为awk中数组的下标可以是数字和字母,数组的下标通常被称为关键字(key)。值和关键字都存储在内部的一张针对key/value应用hash的表格里。由于hash不是顺序存储,因此在显示数组内容时会发现,它们并不是按照你预料的顺序显示出来的。数组和变量一样,都是在使用时自动创建的,awk也同样会自动判断其存储的是数字还是字符串。一般而言,awk中的数组用来从记录中收集信息,可以用于计算总和、统计单词以及跟踪模板被匹配的次数等等。
1.6 使用脚本进行文本、数据处理
BEGIN、END关键字:BEGIN表示处理所有行之前的标识,END表示处理完所有行后的标识,具体语法:
BEGIN{ 这里面放的是执行前的语句}
END {这里面放的是处理完所有的行后要执行的语句}
{这里面放的是处理每一行时要执行的语句}
实例操作文件:cat cal.awk
#!/bin/awk -f
#运行前
BEGIN {
math= 0
english= 0
computer= 0
printf"NAME NO. MATH ENGLISH COMPUTER TOTAL\n"
printf"---------------------------------------------\n"
}
#运行中
{
math+=$3
english+=$4
computer+=$5
printf "%-6s %-6s %4d %8d %8d %8d\n", $1, $2, $3,$4,$5, $3+$4+$5
}
#运行后
END{
printf"---------------------------------------------\n"
printf "TOTAL:%10d %8d %8d \n", math, english, computer
printf "AVERAGE:%10.2f %8.2f %8.2f\n", math/NR, english/NR,computer/NR
}
执行:awk -f cal.awk score.txt
1.7 变量声明和环境变量:使用-v参数进行变量声明,ENVIRON关键字表示环境变量
$ x=5
$ y=10
$ export y #y被export为环境变量
$ echo $x $y
5 10
$awk -v val=$x '{print $1, $2, $3, $4+val, $5+ENVIRON["y"]}' OFS="\t" score.txt
2 sed:流编辑器
stream editor,流编辑器,用程序的方式来编辑文本,正则表达式进行模式匹配。sed本身是一个管道命令,可以分析standard input,也可以将数据进行替换、删除、新增、颉取特定行等功能。
演示文本:catpets.txt
This is my cat
my cat's name is betty
This is my dog
my dog's name is frank
This is my fish
my fish's name is george
This is my goat
my goat's name is adam
使用:sed [-nefr] action
action:-i直接修改读取的档案内容,而不是由屏幕输出,-r表示支持延伸型正则表达式的语法。
动作说明:[n1[,n2]] function n1,n2表示要选择的行数,function包括:
a-新增,c-取代,d-删除,i-插入,p-打印,s-取代(可以直接进行取代的工作,例如 1,20s/old/new/g)
2.1 用s命令进行替换
my字符串替换成Rango Chen’s
sed “s/my/Rango Chen's/g” pets.txt
ps:如果使用单引号,则无法通过\'来转义。该命令并没有对文件内容进行更改,只是把处理过后的内容输出,如果你要写回文件,你可以使用重定向:sed "s/my/Rango Chen's/g" pets.txt >Chen_pets.txt,或者使用-i选项:sed -i “s/my/Rango Chen's/g” pets.txt
s表示替换动作,/g表示一行上的替换所有的匹配。
在每一行最前面加上#:sed 's/^/#/g' pets.txt
在每一行的末尾加上---:sed 's/$/ --- /g' pets.txt
基础的正则表示法特殊字符:
^ 表示一行的开头。如:/^#/ 以#开头的匹配。
$ 表示一行的结尾。如:/}$/ 以}结尾的匹配。
\< 表示词首。如\<abc 表示以abc 为首的詞。
\> 表示词尾。如 abc\> 表示以abc 結尾的詞。
\ 将特殊字符进行转义,还原其本身意义:grep -n \' pets.txt 搜寻含有单引号'的那一行。
. 表示任何单个字符。
* 表示某个字符出现了0次或多次。
[ ] 字符集合。如:[abc]表示匹配a或b或c,还有[a-zA-Z]表示匹配所有的26个字符。如果其中有^表示取反,如[^a]表示非a的字符
\{n,m\} 连续n到m个的“前一个RE字符” grep -n 'go\{2,3\}g' 1.txt 在g与g之间有2到3个o存在的字符串,亦即(goog)(gooog)
去掉某html中的tags:html.txt:
<b>This</b>is what <span style="text-decoration:underline;">I</span> meant. Understand?
sed 's/<[^>]*>//g' html.txt
只替换第3到第6行的文本:sed "3,6s/my/your/g" pets.txt
只替换第3行的文本:sed "3s/my/your/g" pets.txt
只替换每一行的第一个s:sed 's/s/S/1' my.txt 1表示第一个
只替换每一行的第二个s:sed 's/s/S/2' my.txt 2表示第二个
只替换第一行的第3个以后的s:sed 's/s/S/3g' my.txt
2.2 多个匹配
一次替换多个模式,每个模式之间用;进行间隔:sed '1,3s/my/your/g; 3,$s/This/That/g' my.txt
上面的命令等价于:sed -e'1,3s/my/your/g' -e '3,$s/This/That/g' my.txt
使用&来当做被匹配的变量,加入一些字符:sed 's/my/[&]/g' my.txt
此命令相当于在my两边加上[]
2.3 圆括号匹配
圆括号括起来的正则表达式所匹配的字符串会可以当成变量来使用,sed中使用的是\1,\2…
sed 's/This is my \([^,]*\),.*is \(.*\)/\1:\2/g' my.txt
cat:betty
dog:frank
fish:george
goat:adam
2.4 基本知识点
1)Pattern Space:关于参数-n,表示取消默认输出,相当于--quiet,--silent。在sed处理文件的时候,每一行都被保存在一个叫模式空间的临时缓冲区中,除非行被删除或者输出被取消,否则所有被处理的行都将打印在屏幕上。接着模式空间被清空,并存入新的一行等待处理。
2)Address:[address[,address]][!]{cmd},其中的!表示匹配成功后是否执行命令,address可以是一个数字,也可以是一个模式,可以通过逗号分隔两个address表示两个address的区间。
3)命令打包:cmd可以是多个,它们可以用分号分开,可以用大括号括起来作为嵌套命令
对3行到第6行,匹配/This/成功后,再匹配/fish/,成功后执行d命令:
sed '3,6 {/This/{/fish/d}}' pets.txt
从第一行到最后一行,如果匹配到This,则删除之;如果前面有空格,则去除空格:
sed '1,${/This/d ; s/^ *//g}' pets.txt
4)HoldSpace:保持空间
g:将hold space中的内容拷贝到pattern space中,原来pattern space里的内容清除
G:将hold space中的内容append到pattern space\n后
h:将pattern space中的内容拷贝到hold space中,原来的hold space里的内容被清除
H:将pattern space中的内容append到hold space\n后
x:交换pattern space和hold space的内容
sed -e '/test/h' -e '$G‘ example:在这个例子里,匹配test的行被找到后,将存入模式空间,h命令将其复制并存入一个称为保持缓存区的特殊缓冲区内。第二条语句的意思是,当到达最后一行后,G命令取出保持缓冲区的行,然后把它放回模式空间中,且追加到现在已经存在于模式空间中的行的末尾。在这个例子中就是追加到最后一行。简单来说,任何包含test的行都被复制并追加到该文件的末尾。
sed -e '/test/h' -e '/check/x' example:互换模式空间和保持缓冲区的内容。也就是把包含test与check的行互换。
5)执行sed脚本:sed -f test.sed
Sed对于脚本中输入的命令非常挑剔,在命令的末尾不能有任何空白或文本,如果在一行中有多个命令,要用分号分隔。以#开头的行为注释行,且不能跨行。
ps: 去除空白行:sed '/^ *$/d' file
3 sort:文本内容排序
语 法:sort [-bcdfimMnr] [-o<输出文件>] [-t<分隔字符>] [+<起始栏位>-<结束栏位>] [--help] [--verison] [文件]
参 数:
-b 忽略每行前面开始出的空格字符。
-c 检查文件是否已经按照顺序排序。
-d 排序时,处理英文字母、数字及空格字符外,忽略其他的字符。
-f 排序时,将小写字母视为大写字母。
-i 排序时,除了040至176之间的ASCII字符外,忽略其他的字符。
-m 将几个排序好的文件进行合并。
-M 将前面3个字母依照月份的缩写进行排序。
-n 依照数值的大小排序。
-o<输出文件> 将排序后的结果存入指定的文件。
-r 以相反的顺序来排序。
-t<分隔字符> 指定排序时所用的栏位分隔字符。
+<起始栏位>-<结束栏位> 以指定的栏位来排序,范围由起始栏位到结束栏位的前一栏位。
--help 显示帮助。
--version 显示版本信息
4 uniq:Filter adjacent matching lines from INPUT (or standard input), writingto OUTPUT (or standard output)
显示唯一的行,对于那些连续重复的行只显示一次,以及计数重复的行
uniq:不加任何参数表示匹配第一次出现的那行
uniq -c:显示重复的行的行数
uniq -u:仅显示文件中没有连续出现的行,唯一行
uniq -d:仅显示文件中连续重复出现的行。
5 cut:片段颉取工具,可以从一个文本文件或者文本流中提取文本列
5.1 命令用法
cut -b list [-n] [file ...]
cut -c list [file ...]
cut -f list [-d delim][-s][file ...]
-b、-c、-f分别表示字节、字符、字段(即byte、character、field);list表示-b,-c,-f操作范围,-n表示具体数字,with -b: don’t split multibyte characters;file表示的自然是要操作的文本文件的名称;delim(英文全写:delimiter)表示分隔符,默认情况下为TAB;-s表示不包括那些不含分隔符的行(这样有利于去掉注释和标题)。--output-delimiter=字符串,使用指定的字符串作为输出分界符,默认采用输入的分界符。上面三种方式中,表示从指定的范围中提取字节(-b)、或字符(-c)、或字段(-f)。
LIST的范围:
N |
只有第N项 |
N- |
从第N项一直到行尾 |
N-M |
从第N项到第M项(包括M) |
-M |
从一行的开始到第M项(包括M) |
- |
从一行的开始到结束的所有项 |
5.2 用法实例
颉取/etc/passwd文件中的前十五个用户名:
cut -f1 -d: /etc/passwd | head -15
颉取/etc/passwd文件每一行前十个字节的内容:
cut -b 1-10 /etc/passwd
颉取该文件每一行第1,4,7个字节的内容:
cut -b 1,4,7 /etc/passwd
将/etc/passwd的分隔符换成“|”输出:
cut -d: -f 1- -s --output-delimiter=”|” /etc/passwd
6 grep:颉取具有特定信息的行,逐行操作
用法:grep [-acinv] [--color=auto] '搜寻字符串' filename
-a : 将binary档案以text 档案的方式搜寻数据
-c: 计算找到'搜寻字符串'的次数
-i: 忽略大小写的不同,所以大小写视为相同
-n : 顺便输出行号
-v : 反向选择,亦即显示出没有'搜寻字符串'内容的那一行!
--color=auto: 可以将找到的关键词部分加上颜色的显示!
7 wc:wordcount,printnewline, word, and byte counts for each file
用法:wc [-lwmc]
-l : 仅列出行;
-w : 仅列出多少字(英文单字);
-m : 多少字符;
-c: 多少字节
不加任何参数表示全部列出。
实例:/etc/man.config 里面有多少相关字、行、字符数:
cat /etc/man.config | wc