首页 > 代码库 > 第四章 shell学习之sed命令和awk编程
第四章 shell学习之sed命令和awk编程
sed命令
sed只是对缓冲区中原始文件的副本进行编辑,不改变源文件,所以要保存则要重定向到另一个文件
sed三种方式:
1.sed [选项] ‘sed命令‘ 输入文件
2.sed [选项] -f sed脚本文件 输入文件
3../sed脚本文件 输入文件
其中3的sed脚本文件要以#! bin/sed -f等开头
选项:
-n 不打印所有行到标准输出,默认先打印匹配的再打印所有
-e 关联多个sed命令
-f 调用sed脚本文件
定位文本:
x x为指定行号
x,y 从x到y行
/pattern/ 包含模式的行
/pattern/pattern/ 包含两个模式的行
/pattern/,x 从与pattern的匹配行到x行之间的行
x,/pattern/ 从x行到与pattern匹配的行
x,y! 不包括x和y行号的行
sed编辑命令:
p 打印匹配的行
= 打印行号
a\ 在定位行后追加文本信息
i\ 在定位行号之前插入文本信息
d 删除定位行
c\ 用新文本替换定位文本
s 替换模式
r 从另一个文件中读文本
w 将文本写入一个文件
y 变换字符
q 第一个模式匹配完成后退出
l 显示控制字符
{} 在定位行执行的一组命令
n 读取下一个输入行,用下一个命令处理新的行
h 将模式缓冲区的文本复制到保持缓冲区
H 将模式缓冲区的文本追加到保持缓冲区
x 互换模式缓冲区和保持缓冲区的内容
g 将保持缓冲区的内容复制到模式缓冲区
G 将保持缓冲区的内容追加到模式缓冲区
例:
1.
sed -n ‘/clc/p‘ clc.txt
在clc.txt中寻找有clc的行并且输出找到的行,如果没有-n还会输出所有内容
2.
sed -n -e ‘/clc/p‘ -e ‘/clc/=‘ clc.txt
或sed -n ‘/clc/{p;=}‘ clc.txt
或sed -n ‘/clc/p ; /clc/=‘
输出匹配行和行号
3.
cat a.sed
#!/bin/sed -f
/clc\./a\ #如果改为i\则为插入,即在匹配行之情
append a line \
append another line.
chmod u+x a.sed
./a.sed clc.txt
在clc.txt第一个出现clc.的行之后增加两行
4.
sed -n ‘/clc/,$p‘ clc.txt
打印clc.txt的与clc匹配的行到最后一行
5.
sed -n ‘2,10!p‘ clc.txt
打印不在2~10行之间的行
6.
cat a.sed
#!/bin/sed -f
/[Cc][Ll][Cc]/d
chmod u+x a.sed
./a.sed clc.txt
删除带有clc(不管大小写)的行
7.
sed -n ‘s/clc/CLC/2p‘ clc.txt
替换第二次匹配的clc,替换成CLC,注意sed只会把结果(被替换的行)输出到标准输出而不会改变原文件
在替换模式中,p和-n结合为只打印被替换的行
8.
sed -n ‘s/clc/CLC/w output.txt‘ clc.txt
结果输出到output.txt,w为将输出重定向到文件,没有p所有不会打印到屏幕上
9.
sed -n ‘s/clc/(&)/pg‘ clc.txt
全局替换clc为(&),其中&就代表clc
10.
sed -n -e ‘/cl\{3\}c/w output.txt‘ -e ‘/cl\{3\}c/p‘ clc.txt
将匹配clllc的行输出到output.txt并且输出到屏幕
11.
sed -n ‘/cl\{3\}c/q‘ clc.txt
匹配第一个clllc然后打印退出
12.
sed ‘y/12345/ABCDE/‘ clc.txt
y为替换,把clc.txt中的1换成A,2换成B,以此类推
13.
sed -n ‘1,$l‘ clc.txt
显示clc.txt的内容和控制字符,l为显示控制字符
awk编程
awk的三个阶段:
1.读取文件前的执行代码段(由BEGIN标识)
2.读取输入文件时的输入代码段
3.读输入文件完毕之后的执行代码段(由END标识)
awk执行方式:
1.awk [-F 域分隔符] ‘awk程序段’输入文件
2.awk -f awk脚本文件 输入文件
3. ./awk脚本文件 输入文件
注意3方法要在开头表明awk或gawk路径,如#! /bin/awk -f或#! /bin/gawk -f
例:
1.awk模式匹配
awk由模式和动作构成,模式测试输入行是否需要执行动作,动作执行输入行的处理
执行方式1:
[root@localhost tmp]# cat b
[root@localhost tmp]# awk ‘/^$/{print "this is a blank line"}‘ b
this is a blank line
this is a blank line
this is a blank line
this is a blank line
this is a blank line
执行方式2:
[root@localhost tmp]# cat b.awk
/^$/{print "this is a blank line"}
[root@localhost tmp]# awk -f b.awk b
this is a blank line
this is a blank line
this is a blank line
this is a blank line
this is a blank line
执行方式3:
[root@localhost tmp]# which awk
/bin/awk
[root@localhost tmp]# cat b.awk
#! /bin/awk -f
/^$/{print "this is a blank line"}
[root@localhost tmp]# chmod u+x b.awk
[root@localhost tmp]# ./b.awk b
this is a blank line
this is a blank line
this is a blank line
this is a blank line
this is a blank line
2.记录和域
文件由记录组成,记录由域组成,默认一行一条记录,空格或者制表符分割域
[root@localhost tmp]# cat tel
clc,1,234325
clc1,8,258353
clc3,3,234583
clc4,2,345534
[root@localhost tmp]# awk ‘BEGIN{FS=",";one=1;two=2} {print $1 " " $(one+two)}‘ tel
clc 234325
clc1 258353
clc3 234583
clc4 345534
3.关系和布尔运算
$0代表正在处理的记录,$1,$2...代表该记录的域的编号,~为匹配正则表达式,!~为不匹配正则表达式(正则表达式要在//内)
[root@localhost tmp]# awk ‘BEGIN{FS=":"} {if($3>=500 && $0!~/nologin/) print $0}‘ /etc/passwd
clc:x:500:500:clc:/home/clc3:/bin/bash
clc3:x:501:502::/home/clc3:/bin/bash
clc2:x:502:501::/home/clc2:/bin/bash
4.表达式
+,-,*,/,%(模运算),^或**(乘方),++x,x++
[root@localhost tmp]# cat b
[root@localhost tmp]# awk ‘/^$/{print x++}‘ b
0
1
2
3
4
[root@localhost tmp]# awk ‘/^$/{print ++x}‘ b
1
2
3
4
5
5.系统变量
$n 第n个域,域由FS分割
$0 记录所有的域,即当前处理的记录
ARGC 命令行参数的数量(命令本身为参数1)
ARGV 命令行参数数组
ARGIND 命令行中当前文件的位置(以0开始)
CONVFMT 数字转换格式
ENVIRON 环境变量关联数组
ERRNO 最后一个系统错误的描述
FILENAME 当前文件名
FS 字段分割符
RS 记录分隔符
OFS 输出域分隔符,默认为空格
ORS 输出记录分隔符,默认为换行
IGNORECASE 布尔变量,为真则忽略大小写
NF 当前记录的域数量
NR 当前记录数
例1:
[root@localhost tmp]# awk ‘BEGIN{FS=",";OFS=";";ORS="|"} {print NR,NF,$0,"\n"}‘ tel
1;3;clc,1,234325;
|2;3;clc1,8,258353;
|3;3;clc3,3,234583;
|4;3;clc4,2,345534;
例2:
[root@localhost tmp]# cat a4.awk
#! /bin/awk -f
BEGIN{
for(i in ENVIRON)
{print i"="ENVIRON[i];};
}
[root@localhost tmp]# ./a4.awk
TERM=xterm
G_BROKEN_FILENAMES=1
DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-AQhrDkEqnE,guid=9fcb974e6fd4a8e074366f00509e212a
GNOME_DESKTOP_SESSION_ID=Default
SHLVL=2
PWD=/tmp
DESKTOP_SESSION=default
PATH=/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin:/root/bin
...
6.格式化输出
printf修饰符:
- 左对齐
width 域的步长
.prec 小数点右边的位数
printf格式符:
%c ascii字符
%d 整数型
%e 浮点数,科学计数法
%f 浮点数
%o 八进制数
%s 字符串
%x 十六进制数
[root@localhost tmp]# cat tel
clc,1,234325
clc1,8,258353
clc3,3,234583
clc4,2,345534
[root@localhost tmp]# awk ‘BEGIN{FS=","} {printf("%5.2f\t%5s\t%-5d\n",$2,$1,$3)}‘ tel
1.00 clc 234325
8.00 clc1 258353
3.00 clc3 234583
2.00 clc4 345534
7.内置字符串函数
gsub(r,s) 在输入文件中用s替换r,r为/正则表达式/或者"被替换内容",s为"替换内容"
gsub(r,s,t) r在t指定的记录中匹配,比如t为$1
index(s,t) 返回s中字符串第一个t的位置
length(s) 返回s的长度
match(s,t) 测试s是否包含匹配t的字符串,不成功返回0,否则返回离s头部的距离
split(r,s,t) 以t为分隔符分割r,结果存入s数组中,返回分割后的记录数
sub(r,s,t) 将t中第一次出现的r替换为s
substr(r,s) 返回字符串r中从位置s开始的后缀部分
substr(r,s,t) 返回字符串r中从位置s开始长度为t的后缀部分
例:
[root@localhost tmp]# cat a
clc
clllc
cc
abc
cabcc
[root@localhost tmp]# awk ‘gsub(/cl+c/,"kkk") {print $0}‘ a
kkk
kkk
[root@localhost tmp]# awk ‘{gsub(/cl+c/,"kkk");print $0}‘ a
kkk
kkk
cc
abc
cabcc
注意grub在{}和不在{}的区别
[root@localhost tmp]# awk ‘BEGIN{str="hello world";print substr(str,3,6)}‘
llo wo
8.传递参数
[root@localhost tmp]# cat tel
clc,1,234325
clc1,8,258353
clc3,3,234583
clc4,2,345534
[root@localhost tmp]# cat a.awk
#! /bin/awk -f
NF!=MAX
{print("the line "NR" does no have "MAX" filds")}
或者:
[root@localhost tmp]# cat a.awk
#! /bin/awk -f
{print $0;if (NF!=MAX) {print("the line "NR" does no have "MAX" filds")}}
[root@localhost tmp]# ./a.awk MAX=2 FS="," tel
clc,1,234325
the line 1 does no have 2 filds
clc1,8,258353
the line 2 does no have 2 filds
clc3,3,234583
the line 3 does no have 2 filds
clc4,2,345534
the line 4 does no have 2 filds
9.条件和循环语句
if else
如:if(x~/[Hh]el?o/) print x
while
do while
for
例:
[root@localhost tmp]# cat a2.awk
#! /bin/awk -f
BEGIN{
for(i=0;i<ARGC;i++)
{
printf("arg%d is %s\n",i,ARGV[i]);
};
printf("there are %d arg\n",ARGC);
}
[root@localhost tmp]# ./a2.awk a1 a2 a3
arg0 is awk
arg1 is a1
arg2 is a2
arg3 is a3
there are 4 arg
10.数组
array[索引]=值
for(索引 in array)
例1:
[root@localhost tmp]# cat a1.awk
#! /bin/awk -f
BEGIN{
str="str1/str2/str3";
print split(str,result,"/");
for(fild in result)
{
print result[fild];
}
}
例2:
[root@localhost tmp]# cat a3.awk
#! /bin/awk -f
BEGIN{
FS=",";
if(ARGC>2)
{
name=ARGV[1];
delete ARGV[1];
}
else
{
while(!name)
{
print "please enter a name:";
getline name< "-"; #从标准输入中读取
}
};
}
{
if($1~name)
{print $1,$3;};
}
[root@localhost tmp]# cat tel
clc,1,234325
clc1,8,258353
clc3,3,234583
clc4,2,345534
abc,5,2343243
[root@localhost tmp]# ./a3.awk abc tel
abc 2343243
[root@localhost tmp]# ./a3.awk tel
please enter a name:
abc
abc 2343243
本文出自 “flyclc” 博客,请务必保留此出处http://flyclc.blog.51cto.com/1385758/1540162