sed
sed逐行处理文件(输入),并将结果发送到屏幕。
sed把当前正在处理的行保存在一个临时缓区(模式空间)中,sed处理完缓冲区中的内容后把其发送到屏幕上。
处理完一行之后自动进行下一行的处理,直到文件末行为止。
语法
sed [options] '{command}' [filename]
options:
-n抑制默认输出 -r使用扩展的正则表达式
-i编辑文件内容 -i.bak修改文件的同时生成源文件的.bak的备份
-e执行sed命令(执行多个命令时使用)
-f读取sed脚本文件
command:
a在匹配后追加 i在匹配前插入 c替换 y转换
p打印 d删除
r读取文件 w另存为
h/H拷贝/追加模式空间到存放空间 g/G从存放空间取回/追加到模式空间
s搜索
例:
显示文件第三行
#sed -n '3p' file.txt
显示文件前三行
#sed -n '1,3p' file.txt
不显示文件的前三行
#sed -n '1,3!p' file.txt
显示文件的第二行,和后面三行
#sed -n '2,+3p' file.txt
显示文件最后一行
#sed -n '$p' file.txt
显示文件行数
#sed -n '$=' /etc/passwd
给脚本添加#!/bin/bash
#sed -i.bak '1i\#!/bin/bash' shell.sh
修改脚本的#!
#sed -i.bak '1c#!/bin/sh' shell.sh
复制/剪切粘贴
#sed '2h;$G' file.txt 复制
#sed '2{h;d};$G' file.txt 剪切
#sed '2h;3,4H;$G' file.txt
#sed '2{h;d};3,4{H;d};$G' file.txt
sed中的正则
^ $ * + ? [] {} ()
&代表之前匹配到的内容
#sed '/正则/p' file.txt
删除带注释
#sed -i '/^#/d' squid.conf
删除空行
#sed '/^$/d' squid.conf
掉换文件的两字段
#cat file.txt
xxxrootxxxbobxxx
#sed -r 's/(.*)(root)(.*)(bob)(.*)/\1\4\3\2\5/g' file.txt
xxxbobxxxrootxxx
文件加/删除注释
#sed -i '21,25s/^/#/' shell.sh
#sed -i '21,25s/^#//' shell.sh
文件格式转换 win:\r\n unix:\n
#sed -i 's/$/\r/' shell.txt #unix2dos 软件:editra notepad++ ultraedit
#sed -i 's/\r//' shell.txt #dos2unix
修改主机名 - 修改成server1.example.com
#hostname server1.example.com
#sed -r 's/(HOSTNAME=)(.*)/\1server1.example.com/' /etc/sysconfig/network
#sed -i 's/HOSTNAME=.*/HOSTNAME=zhaoyun/com/g' /etc/sysconfig/network
转换MAC地址
#echo 005056C00001 | sed -r 's/([a-zA-Z0-9]{2})/\1:/g'
#echo 005056C00001 | sed -r 's/([a-zA-Z0-9]{2})/\1:/g;s/(.+):/\1/'
模式和动作
awk的所有语句都是由模式和动作组成,先模式后动作。
BEGIN是在任何动作执行之前进行的。
END是在任何动作执行之后进行的。
域和记录
域:~列 用FS(awk的内部变量)分割的每一部分
记录:~行 用RS(awk的内部变量)分割的每一部分
操作符
空格 表示字符串的连接
()组 $引用字段(自定义变量)
++ --
+ - * % /
= += -= *= %= /= ^=
&& ||
?: (C风格的条件表达式)
~正则匹配 !~正则不匹配
\t \n \r...
控制语句
if (condition) statement [else statement]
while (condition) statement
do statement while (condition)
for (expr1;expr2;expr3) statement
array[0]=value
break
continue
语法:
awk [options] 'pattern {action}' [file]
-f读取awk脚本文件 -F指定分割符(FS)
#!/bin/awk -f
例
result:
andy 4 85 92 78 94 88
bob 6 89 90 75 90 86
claire 9 84 88 80 95 84
dave 5 94 58 36 78 NA
显示全部内容
#awk '{print $0}' result
显示第一列
#awk '{print $1}' result
显示1-3列
#awk '{print $1,$2,$3}' result
带头信息的显示
#awk 'BEGIN {print "姓名","年级","数学"} {print $1,$3}' result
带头信息的显示(格式化后)
#awk 'BEGIN {print "名\t年级\t数学"} {print $1"\t"$2"\t"$3}' result
计算平均成绩
#awk 'BEGIN {print "名\t年级\t平均分"} {print $1"\t"$2"\t"($3+$4+$5+$6+$7)/5}' result
显示第二列等于6/大于等于6的行
#awk '$2 ~ /6/ {print $0}' result
#awk '$2 >= 6 {print $0}' result
分割符FS
#awk -F ":" 'BEGIN {print "用户名\tUID\tGID"} {print $1"\t"$3"\t"$4}' /etc/passwd
批量修改文件名:
#ls access.20111202.log.bak | awk -F"." '{print "mv",$0,$1"."$2"."$3}' | bash
格式化输出
printf
-左对齐 +(或省略)右对齐
%d十进制整数
%s字符串
%c字符
%i整数
%f浮点数
%o无符号八进制
%u无符号十进制
%x无符号十六进制
例:
控制字符对齐
#awk 'END {printf ("|%-10s|\n","hello")}' result
df命令的输出改写成MB
#LANG=C df | grep -v 'Use' | awk '$4 > 20000{OFMT="%.2f";print $1,$4/1024,"MB"}'
乘法表
#awk 'BEGIN {for (i=1;i<10;i++) {for (j=1;j<=i;j++) {printf "%d%s%d%s%d\t",j,"*",i,"=",j*i;}printf"\n"} }'
awk的函数
index子字符在父字符串中出现的位置
#awk 'BEGIN {print index("hello","e")}'
sub在记录中查找能够匹配的最长内容并且左续替换
#awk '{sub(/dave/,"eide",$1);print}' result
substr返回从字符串指定位置开始的一个新字符串
#awk 'BEGIN {print substr("Hello World again",7,5)}'
split把字符串分割成数组
#awk 'BEGIN {split("14/02/2010",nowdate,"/");print nowdate[3]}'
awk常见内部变量
FS输入分割符 OFS输出分割符
RS行分割符 ORS输出行分割符
NF当前域个数 NR当前记录的个数
ARGC命令行参数的个数 ARGV命令行参数的数组
FILENAME处理的文件名
例:
#awk '/^$/{print NR}' result
#awk '{print $(NF-1)}' result
#awk '{print NF,NR,$0} END {print FILENAME,ARGC,ARGV[0]}' result
#awk '{FS=":";OFS="\t";ORS="\n"}{print $1,$2,$3}' /etc/passwd
本文转自zhaoyun00 51CTO博客,原文链接:http://blog.51cto.com/zhaoyun/750759