天天看点

sed awk

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

格式化输出

print

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

继续阅读