awk
# 格式
$ awk 'pattern1 {action1} pattern2 {action2}...' filename
其中pattern代表匹配模式,actions表示要执行的操作,pattern和actions都是可选的,但是两者必须至少有一个;
工作流程:(反复执行4个步骤)
1、自动从指定的数据文件中读取行文本
2、自动更新awk的内置系统变量的值,例如列数变量NF、行数变量NR、行变量$0以及各个列变量$1、$2等
3、依次执行程序中所有的匹配模式及其操作
4、当执行完程序中所有的匹配模式及其操作之后,如果数据文件中仍然还有未读取的数据行,则返回到第1步,重复执行1-4的操作。
# 示例1
$ awk '{print $0}' demo.txt
$0代表当前行,$1、$2、$3代表第一个字段、第二个字段、第三个字段
$0变量代表整条记录。$1、$2代表第一个字段、第二个字段,......以此类推。
# 示例2 相邻两行相减
awk 'NR==1 {tmp=$1} NR>1{print $1-tmp;tmp=$1}' demo.txt
匹配到第一行数据,执行赋值操作tmp=$1, 匹配到之后行的数据,执行打印加赋值操作{print $1-tmp;tmp=$1}
# 示例3 过滤内容大于1的行
awk '$1>1' demo.txt
#示例4 过滤出文件内不是数字的那一行
~:正则表达式 匹配
!~:正则表达式 不匹配
awk '{if($0 !~ /^[0-9]+$/) print $0;}' demo.txt
#示例5 求和
awk '{sum+=$1} END {print "Sum = ", sum}' demo.txt
#示例6 求平均
awk '{sum+=$1} END {print "Average = ", sum/NR}' demo.txt
#示例7 求最大值
sort -n demo.txt | tail -n 1
#示例8 求最小值
sort -n demo.txt | head -n 1
#示例9 awk配合eval实现快速变量
eval `free -h | awk 'NR==2{print}' |awk '{printf("t=%s\nu=%s\nf=%s\n"), $2,$3,$4}'`
echo $t, $u, $f
#示例10 求最大值,最小值和去掉最大值最小值的平均值
-
eval $(awk 'BEGIN{max=0}{if ($1!="" && $1>max) max=$1}END{printf("maxval=%d", max)}' abc.txt)
-
echo "max: " $maxval >> output.txt
-
#awk配合eval实现快速变量
-
eval $(awk 'BEGIN{min=9999}{if ($1!="" && $1<min) min=$1}END{printf("minval=%d", min)}' abc.txt)
-
echo "min: " $minval >> output.txt
-
#awk中引用shell变量,双引号、单引号、${var}、单引号、双引号
-
awk '$1!="" && $1!="'$maxval'" && $1!="'$minval'" {sum+=$1}END{print "average: ", sum/NR}' abc.txt >> output.txt
awk分隔符
-F指定输入分隔符,默认为空格
-
# 示例
-
awk -F ':' '{ print $1 }' demo.txt
-
awk -F: '/root/{print $7}' /etc/passwd
-
#搜索/etc/passwd有root关键字的所有行,并显示对应的shell
如果只是显示/etc/passwd的账户和账户对应的shell,而账户与shell之间以逗号分割,而且在所有行添加列名name,shell,在最后一行添加"blue,/bin/nosh"。
-
# 示例
-
cat /etc/passwd |awk -F ':' 'BEGIN {print "name,shell"} {print $1","$7} END {print "blue,/bin/nosh"}'
-
# 输出
-
name,shell
-
root,/bin/bash
-
daemon,/bin/sh
-
bin,/bin/sh
-
sys,/bin/sh
-
....
-
blue,/bin/nosh
awk工作流程是这样的:先执行BEGIN,然后读取文件,读入有/n换行符分割的一条记录,然后将记录按指定的域分隔符划分域,填充域,$0则表示所有域,$1表示第一个域,$n表示第n个域,随后开始执行模式所对应的动作action。接着开始读入第二条记录······直到所有的记录都读完,最后执行END操作。
逗号分隔变量,通过awk的内置变量OFS设定awk的输出分隔符,使用变量的时候要配合使用-v选项,默认为空格
-
# 示例
-
awk -F ':' -v OFS="__" '{ print $1,$2 }' demo.txt
awk内置变量
awk有许多内置变量用来设置环境信息,这些变量可以被改变,下面给出了最常用的一些变量。
ARGC 命令行参数个数
ARGV 命令行参数排列
ENVIRON 支持队列中系统环境变量的使用
FILENAME awk浏览的文件名
FNR 浏览文件的记录数
FS 设置输入域分隔符,等价于命令行 -F选项
NF 浏览记录的域的个数
NR 已读的记录数
OFS 输出域分隔符
ORS 输出记录分隔符
RS 控制记录分隔符
统计/etc/passwd:文件名,每行的行号,每行的列数,对应的完整行内容:
-
awk -F ':' '{print "filename:" FILENAME ",linenumber:" NR ",columns:" NF ",linecontent:"$0}' /etc/passwd
-
# 输出
-
filename:/etc/passwd,linenumber:1,columns:7,linecontent:root:x:0:0:root:/root:/bin/bash
-
filename:/etc/passwd,linenumber:2,columns:7,linecontent:daemon:x:1:1:daemon:/usr/sbin:/bin/sh
-
filename:/etc/passwd,linenumber:3,columns:7,linecontent:bin:x:2:2:bin:/bin:/bin/sh
-
filename:/etc/passwd,linenumber:4,columns:7,linecontent:sys:x:3:3:sys:/dev:/bin/sh
awk自定义变量
获取最后一列
awk -F',' '{print $NF}'
下面统计/etc/passwd的账户人数
-
awk '{count++;print $0;} END{print "user count is ", count}' /etc/passwd
-
# 输出
-
root:x:0:0:root:/root:/bin/bash
-
......
-
user count is 40
count是自定义变量。之前的action{}里都是只有一个print,其实print只是一个语句,而action{}可以有多个语句,以;号隔开。
这里没有初始化count,虽然默认是0,但是妥当的做法还是初始化为0:
-
awk 'BEGIN {count=0;print "[start]user count is ", count} {count=count+1;print $0;} END{print "[end]user count is ", count}' /etc/passwd
-
# 输出
-
[start]user count is 0
-
root:x:0:0:root:/root:/bin/bash
-
...
-
[end]user count is 40
awk结果作为grep查找的关键字
awk '{print $1}' | xargs -i grep {} test.txt
grep
满足任意条件(word1、word2和word3之一)将匹配。
grep -E "word1|word2|word3" file.txt
必须同时满足三个条件(word1、word2和word3)才匹配。
grep word1 file.txt | grep word2 |grep word3
排除 abc.txt 中的 mmm nnn
grep -v 'mmm\|nnn' abc.txt
sed
sed基础指令
删除匹配行
sed -i '/preSql/d' a.txt
删除指定行
sed -i '1d' a.txt
从第三行开始,每隔一行删除
sed -i '3~2d' a.txt
删除从第4行到第8行
sed -i '4,8d' a.txt
删除最后一行
sed -i '$d' a.txt
删除所有空行
sed '/^$/d' a.txt
从匹配行到末尾行
sed -i '/Website Design/,$d' a.txt
删除匹配行和之后两行
sed -i '/Storage/,+2d' a.txt
sed正则表达式替换
-
# -i 就地替换
-
# -E 正则表达式匹配
-
# 请注意*前面的.
-
sed -i -E 's/boys.*girls/mmm/g' file.txt
sed 执行多条命令
sed -e 's/cat/dog/g' -e 's/=//g'
sed 保留每一行的第一到第n个字符
sed -r 's/(.{3}).*/\1/' test.txt
第一列重复,拼接第一列,和其他行的第二列
-
cat 2.txt
-
#输出
-
adc 3 5
-
a d a
-
a 3 adf
-
a d b
-
a 3 adf
-
awk '{a[$1]=a[$1] ";"$2} END{for (i in a)print i,a[i]}' 2.txt
-
#输出
-
a d 3 d 3