sed:Stream EDitor 流编辑器
默认不编辑原文件,仅对模式空间中的数据做匹配,匹配成功的则打印至屏幕。
模式空间:一开始先复制存放一份文本的副本。
sed [options] 'AddressCommand' file,...
-n:静默模式,不再默认显示模式空间中的内容
-i:直接修改原文件
-e:SCRIPT -e SCRIPT:可以同时执行多个脚本,'AddressCommand'看作是一个脚本
-f /PATH/TO/SED_SCRIPT:执行指定文件中的脚本
-r:表示使用扩展正则表达式
Address:
1.StartLine,EndLine
例如1,100
$:表示最后一行
2./RegExp/
/^root/
3./pattern1/,/pattern2/
第一次被pattern1匹配到的行开始,到第一次被pattern2匹配到的行结束,这中间的所有行
4.LineNumber
指定的行
5.StartLine,+N
从StartLine开始,向后的N行
Command:
d:删除符合条件的行
p:显示符合条件的行;
a \string:在指定的行后面追加新行,内容为string
\n:可以用于换行
i \string:在指定的行前面添加新行,内容为string
r FILE:将指定的文件的内容添加至符合条件的行处
w FILE:将地址指定的范围内的行另存至指定的文件中
s/pattern/string/修饰符:查找并替换,默认只替换每行中第一次被模式匹配到的字符串
加修饰符
g:全局替换
i:忽略字符大小写
s///:s###,s@@@
\(string\), \1,\2后向引用
&:引用模式匹配到的整个字符串
例子:sed "s#l..e#&r#g" <--> sed "s#\(l..e\)#\1r#g"
sed "s#l\(..e\)#L\1#g"
sed练习:
1、删除/etc/grub.conf文件中行首的空白符;
sed -r 's@^[[:spapce:]]+@@g' /etc/grub.conf
2、替换/etc/inittab文件中"id:3:initdefault:"一行中的数字为5;
sed 's@\(id:\)[0-9]\(:initdefault:\)@\15\2@g' /etc/inittab
3、删除/etc/inittab文件中的空白行;
sed '/^$/d' /etc/inittab
4、删除/etc/inittab文件中开头的#号;
sed 's@^#@@g' /etc/inittab
5、删除某文件中开头的#号及后面的空白字符,但要求#号后面必须有空白字符;
sed -r 's@^#[[:space:]]+@@g' /etc/inittab
6、删除某文件中以空白字符后面跟#类的行中的开头的空白字符及#
sed -r 's@^[[:space:]]+#@@g' /etc/inittab
7、取出一个文件路径的目录名称;
echo "/etc/rc.d/" | sed -r 's@^(/.*/)[^/]+/?@\1@g'
基名:
echo "/etc/rc.d/" | sed -r 's@^/.*/([^/]+)/?@\1@g'
awk:报告生成器,格式化文本后进行打印显示
awk [options] 'script' file1 file2, ...
awk [options] 'PATTERN { action }' file1 file2, ...
常用options:
-F:指定分隔符
-v VAR=value:在命令行中对变量进行赋值
一、print
print的使用格式:
print item1, item2, ...
要点:
1、各项目之间使用逗号隔开,而输出时则以空白字符分隔;
2、输出的item可以为字符串或数值、当前记录的字段(如$1)、变量或awk的表达式;数值会先转换为字符串,而后再输出;
3、print命令后面的item可以省略,此时其功能相当于print $0, 因此,如果想输出空白行,则需要使用print "";
例子:
awk 'BEGIN { print "line one\nline two\nline three" }' awk -F: '{ print $1, $3 }' /etc/passwd
二、awk变量
2.1 awk内置变量之记录变量:
FS: field separator,读取文本时,所使用的字段分隔符
RS: Record separator,输入文本信息所使用的换行符
OFS: Output Filed Separator,输出文本时,所使用的字段分隔符
ORS:Output Row Separator,输出文本信息所使用的换行符
例子:
awk -F: '{print $1,$3}' /etc/passwd
awk 'BEGIN{FS=":";OFS="#";"ORS="\t"}{print $1,$3}'
[root@localhost ~]# awk 'BEGIN{FS=":";OFS="#";ORS="\t"}{print $1,$3}' /etc/passwd root#0 bin#1 daemon#2 adm#3 lp#4 sync#5 shutdown#6 halt#7 mail#8 news#9 uucp#10 operator#11 games#12 gopher#13 ftp#14 nobody#99 distcache#94 nscd#28 vcsa#69 pcap#77 ntp#38 dbus#81 apache#48 avahi#70 rpc#32 mailnull#47 smmsp#51 sshd#74 webalizer#67 oprofile#16 squid#23 rpcuser#29 nfsnobody#65534 xfs#43 haldaemon#68 avahi-autoipd#100 gdm#42 sabayon#86 chenqiyi#500 named#25 mysql#27 hadoop#520 [root@localhost ~]#
2.2awk内置变量之数据变量:
NR: The number of input records,awk命令所处理的记录数;如果有多个文件,这个数目会把处理的多个文件中行统一计数;
NF:Number of Field,当前记录的field个数;
FNR: 与NR不同的是,FNR用于记录正处理的行是当前这一文件中被总共处理的行数;
ARGV: 数组,保存命令行本身这个字符串,如awk '{print $0}' a.txt b.txt这个命令中,ARGV[0]保存awk,ARGV[1]保存a.txt;
ARGC: awk命令的参数的个数;
FILENAME: awk命令所处理的文件的名称;
ENVIRON:当前shell环境变量及其值的关联数组;
例子:
[root@localhost ~]# awk -F: '/^[rh]/{print NR}' /etc/passwd 1 8 25 32 35 42 [root@localhost ~]# awk -F: '/^[rh]/{print NF}' /etc/passwd 7 7 7 7 7 7 [root@localhost ~]# awk -F: '/^r/{print ARGV[0],ARGV[1],ARGC,FILENAME,ENVIRON["PWD"]}' /etc/passwd awk /etc/passwd 2 /etc/passwd /root awk /etc/passwd 2 /etc/passwd /root awk /etc/passwd 2 /etc/passwd /root
awk 'BEGIN{print ENVIRON["PATH"]}'
2.3用户自定义变量
gawk允许用户自定义自己的变量以便在程序代码中使用,变量名命名规则与大多数编程语言相同,只能使用字母、数字和下划线,且不能以数字开头。gawk变量名称区分字符大小写。
2.3.1在脚本中赋值变量:
在gawk中给变量赋值使用赋值语句进行,例如:
awk 'BEGIN{var="variable testing";print var}'
2.3.2在命令行中使用赋值变量:
gawk命令也可以在“脚本”外为变量赋值,并在脚本中进行引用。例如,上述的例子还可以改写为:
awk -v var="variable testing" 'BEGIN{print var}'
三、printf:按指定格式对数据进行输出
printf命令的使用格式:
printf format, item1, item2, ...
要点:
1、其与print命令的最大不同是,printf需要指定format;
2、format用于指定后面的每个item的输出格式;
3、printf语句不会自动打印换行符'\n'
format格式的指示符都以%开头,后跟一个字符;如下:
%c: 显示字符的ASCII码;
%d, %i:十进制整数;
%e, %E:科学计数法显示数值;
%f: 显示浮点数;
%g, %G: 以科学计数法的格式或浮点数的格式显示数值;
%s: 显示字符串;
%u: 无符号整数;
%%: 显示%自身;
修饰符:
N: 显示宽度;
-: 左对齐;
+:显示数值符号;
例子:
[root@localhost ~]# awk -F: '{printf "%-15s %i\n",$1,$3}' /etc/passwd root 0 bin 1 daemon 2 adm 3 lp 4 sync 5 shutdown 6 halt 7 mail 8 news 9 uucp 10 operator 11 games 12 gopher 13 ftp 14 nobody 99 distcache 94 nscd 28 vcsa 69 pcap 77 ntp 38 dbus 81 apache 48 avahi 70 rpc 32 mailnull 47 smmsp 51 sshd 74 webalizer 67 oprofile 16 squid 23 rpcuser 29 nfsnobody 65534 xfs 43 haldaemon 68 avahi-autoipd 100 gdm 42 sabayon 86 chenqiyi 500 named 25 mysql 27 hadoop 520
四、输出重定向
print items > output-file
print items >> output-file
print items | command
特殊文件描述符:
/dev/stdin:标准输入
/dev/sdtout: 标准输出
/dev/stderr: 错误输出
/dev/fd/N: 某特定文件描述符,如/dev/stdin就相当于/dev/fd/0;
例子:
# awk -F: '{printf "%-15s %i\n",$1,$3 > "/dev/stderr" }' /etc/passwd
五、awk的操作符
5.1 算术操作符:
-x: 负值
+x: 转换为数值;
x^y:
x**y: 次方
x*y: 乘法
x/y:除法
x+y:
x-y:
x%y:
5.2 字符串操作符:
只有一个,而且不用写出来,用于实现字符串连接;
5.3 赋值操作符:
=
+=
-=
*=
/=
%=
^=
**=
++
--
需要注意的是,如果某模式为=号,此时使用/=/可能会有语法错误,应以/[=]/替代;
5.4 布尔值
awk中,任何非0值或非空字符串都为真,反之就为假;
5.5 比较操作符:
x < yTrue if x is less than y.
x <= yTrue if x is less than or equal to y.
x > yTrue if x is greater than y.
x >= yTrue if x is greater than or equal to y.
x == yTrue if x is equal to y.
x != yTrue if x is not equal to y.
x ~ yTrue if the string x matches the regexp denoted by y.
x !~ yTrue if the string x does not match the regexp denoted by y.
subscript in array True if the array array has an element with the subscript subscript.
5.7 表达式间的逻辑关系符:
&&
||
5.8 条件表达式:
selector?if-true-exp:if-false-exp
if selector; then
if-true-exp
else
if-false-exp
fi
a=3
b=4
a>b?a is max:b ia max
5.9 函数调用:
function_name (para1,para2)
六、awk的模式
awk 'program' input-file1 input-file2 ...
其中的program为:
pattern { action }
pattern { action }
...
6.1 常见的模式类型:
1、Regexp: 正则表达式,格式为/regular expression/
2、expresssion: 表达式,其值非0或为非空字符时满足条件,如:$1 ~ /foo/ 或 $1 == "magedu",用运算符~(匹配)和!~(不匹配)。
3、Ranges: 指定的匹配范围,格式为pat1,pat2
4、BEGIN/END:特殊模式,仅在awk命令执行前运行一次或结束前运行一次
5、Empty(空模式):匹配任意输入行;
/正则表达式/:使用通配符的扩展集。
关系表达式:可以用下面运算符表中的关系运算符进行操作,可以是字符串或数字的比较,如$2>%1选择第二个字段比第一个字段长的行。
模式匹配表达式:
模式,模式:指定一个行的范围。该语法不能包括BEGIN和END模式。
BEGIN:让用户指定在第一条输入记录被处理之前所发生的动作,通常可在这里设置全局变量。
END:让用户在最后一条输入记录被读取之后发生的动作。
6.2 常见的Action
1、Expressions:
2、Control statements
3、Compound statements
4、Input statements
5、Output statements
七、控制语句
7.1 if-else
语法:if (condition) {then-body} else {[ else-body ]}
例子:
awk -F: '{if ($1=="root") print $1, "Admin"; else print $1, "Common User"}' /etc/passwd
awk -F: '{if ($1=="root") printf "%-15s: %s\n", $1,"Admin"; else printf "%-15s: %s\n", $1, "Common User"}' /etc/passwd
awk -F: -v sum=0 '{if ($3>=500) sum++}END{print sum}' /etc/passwd
7.2 while
语法: while (condition){statement1; statment2; ...}
例子:
awk -F: '{i=1;while (i<=3) {print $i;i++}}' /etc/passwd
awk -F: '{i=1;while (i<=NF) { if (length($i)>=4) {print $i}; i++ }}' /etc/passwd
7.3 do-while
语法: do {statement1, statement2, ...} while (condition)
例子:
awk -F: '{i=1;do {print $i;i++}while(i<=3)}' /etc/passwd
7.4 for
语法: for ( variable assignment; condition; iteration process) { statement1, statement2, ...}
例子:
awk -F: '{for(i=1;i<=3;i++) print $i}' /etc/passwd
awk -F: '{for(i=1;i<=NF;i++) { if (length($i)>=4) {print $i}}}' /etc/passwd
for循环还可以用来遍历数组元素:
语法: for (i in array) {statement1, statement2, ...}
例子:
awk -F: '$NF!~/^$/{BASH[$NF]++}END{for(A in BASH){printf "%15s:%i\n",A,BASH[A]}}' /etc/passwd
7.5 case
语法:switch (expression) { case VALUE or /REGEXP/: statement1, statement2,... default: statement1, ...}
7.6 break 和 continue
常用于循环或case语句中
7.7 next
提前结束对本行文本的处理,并接着处理下一行;例如,下面的命令将显示其ID号为奇数的用户:
# awk -F: '{if($3%2==0) next;print $1,$3}' /etc/passwd
八、awk中使用数组
8.1 数组
array[index-expression]
index-expression可以使用任意字符串;需要注意的是,如果某数据组元素事先不存在,那么在引用其时,awk会自动创建此元素并初始化为空串;因此,要判断某数据组中是否存在某元素,需要使用index in array的方式。
要遍历数组中的每一个元素,需要使用如下的特殊结构:
for (var in array) { statement1, ... }
其中,var用于引用数组下标,而不是元素值;
例子:
netstat -ant | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
每出现一被/^tcp/模式匹配到的行,数组S[$NF]就加1,NF为当前匹配到的行的最后一个字段,此处用其值做为数组S的元素索引;
awk '{counts[$1]++}; END {for(url in counts) print counts[url], url}' /var/log/httpd/access_log
用于统计某日志文件中IP地址的访问量
8.2 删除数组变量
从关系数组中删除数组索引需要使用delete命令。使用格式为:
delete array[index]
九、awk的内置函数
split(string, array [, fieldsep [, seps ] ])
功能:将string表示的字符串以fieldsep为分隔符进行分隔,并将分隔后的结果保存至array为名的数组中;数组下标为从0开始的序列;
netstat -ant | awk '/:80\>/{split($5,clients,":");IP[clients[1]]++}END{for(i in IP){print IP[i],i}}' | sort -rn | head -50
length([string])
功能:返回string字符串中字符的个数;
substr(string, start [, length])
功能:取string字符串中的子串,从start开始,取length个;start从1开始计数;
system(command)
功能:执行系统command并将结果返回至awk命令
systime()
功能:取系统当前时间
tolower(s)
功能:将s中的所有字母转为小写
toupper(s)
功能:将s中的所有字母转为大写
十一、用户自定义函数
自定义函数使用function关键字。格式如下:
function F_NAME([variable])
{
statements
}
函数还可以使用return语句返回值,格式为“return value”。