您的位置:首页 > 运维架构 > Linux

linux sed,awk详解

2015-09-16 16:31 465 查看
sed命令:
sed 是一种在线编辑器,它一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有 改变,除非你使用重定向存储输出。Sed主要用来自动编辑一个或多个文件;简化对文件的反复操作;编写转换程序等。
sed使用参数
[root@www ~]# sed [-nefr] [动作]
-n :使用安静(silent)模式。在一般 sed 的用法中,所有来自 STDIN 的数据一般都会被列出到终端上。
但如果加上 -n 参数后,则只有经过sed 特殊处理的那一行(或者动作)才会被列出来。
-e :直接在命令列模式上进行 sed 的动作编辑;
-f :直接将 sed 的动作写在一个文件内, -f filename 则可以运行 filename 内的 sed 动作;
-r :sed 的动作支持的是延伸型正规表示法的语法。(默认是基础正规表示法语法)
-i :直接修改读取的文件内容,而不是输出到终端。
s/regexp/replacement/:替换由regexp所匹配到的内容为replacement
w /path/to/somefile:把指定的内容另存至/path/to/somefile路径所指定的文件中
r /path/from/somefile:在文件的指定位置插入另一个文件的所有内容,完成文件合并
function:
a :新增, a 的后面可以接字串,而这些字串会在新的一行出现(目前的下一行)
c :取代, c 的后面可以接字串,这些字串可以取代 n1,n2 之间的行
d :删除,因为是删除啊,所以 d 后面通常不接任何咚咚
i :插入, i 的后面可以接字串,而这些字串会在新的一行出现(目前的上一行)
p :列印,亦即将某个选择的数据印出。通常 p 会与参数 sed -n 一起运行
s :取代,可以直接进行取代的工作哩!通常这个 s 的动作可以搭配正规表示法
1. 定址:定址用于决定对哪些行进行编辑。地址的形式可以是数字、正则表达式、或二者的结合。如果没有指定地址,sed将处理输入文件的所有行。
#:指定行
$:最后一行
/regexp/:任何能够被regexp所匹配的到的行
\%regexp%:同上,只是换作%为regexp的边界符
/regexp/|:匹配时忽略字符大小写
\%regexp%|:匹配时忽略字符大小写
startline,endline
#,/regexp/:从#行开始,到第一次被/regexp/所匹配到的行结束,中间所有的行
/regexp/,/regexp2/:从第一次被/regexp/所匹配到的行,到被/regexp2/所匹配的行结束,中间所有的行
#,+n:从#行开始,再向下的n行
#,$:从#开始到最后一行
first~step:指定起始行,以及步长
2.d,删除行
例1.[root@lys ~]# sed '2d' /etc/fstab



例2.删除/etc/fstab第五行后所有的行,$代表末行
[root@lys ~]# sed '5,$d' /etc/fstab



3.p命令:命令p用于显示模式空间的内容。默认情况下,sed把输入行打印在屏幕上,选项-n用于取消默认的打印操作。当选项-n和命令p同时出现时,sed可打印选定的内容。
例3.
[root@lys ~]# sed -n '/UUID/p' /etc/fstab



4.s命令:格式:sed 's/要替换的字符串/新的字符串/g' (要替换的字符串可以用正则表达式)
例4.1将/etc/fstab中的UUID 替换成AAID



例4.2删除/etc/selinux/config文件中所有以#开头,后跟至少一个空白字符的行的行首的#和空白字符



5.first~step:指定起始行,以及步长。w命令是读入一个文件内容
例5.1将/etc/passwd文件的奇数行保存到/tmp/passwd中,其中sed 1~2表示从第一行开始,以2行为一个跨度进行匹配






6.e选项:-e是编辑命令,用于sed执行多个编辑任务的情况下。在下一行开始编辑前,所有的编辑动作将应用到模式缓冲区中的行上。
例6.先匹配“root”的行,然后将“root”替换成“adm”



7.i\命令:i\ 命令是在当前行的前面插入新的文本。
例7.在/etc/passwd的第四行前插入test



8.r命令:r命令是读命令。sed使用该命令将一个文本文件中的内容加到当前文件的特定位置上。



9.sed的一些特殊命令如下:
高级命令:

h:用模式空间中的内容覆盖保持空间的内容;
H:把模式空间中的内容追加至保持空间中内容的后面;
g:从保持空间中取到其内容,并将其覆盖模式空间中的内容;
G:从保持空间中取到其内容,并将其追加在模式空间中的内容的后面;
x:把保持空间和模式空间中的进行交换;
n:读取匹配到的行的下一行至模式空间;(会覆盖模式空间中的原有内容);
N:读取匹配到的行的下一行至模式空间,追加在模式空间中原有内容的后面;
d:删除模式空间中的内容;
D:删除多行模式空间中的首行;
注意:命令功能可使用!取反;分号可用于分隔脚本;

sed 'G' /etc/issue: 在文件中的每行后方添加空白行;

sed '$!d' /etc/fstab:保留最后一行;
sed '/^$/d;G' /etc/issue: 保证指定的文件每一行后方有且只有一个空白行;
sed 'n;d' /etc/issue:保留奇数行;
sed -n '1!G;h;$p' /etc/issue
sed '$!N;$!D' /etc/issue

awk命令详解

什么是awk?awk是三个人名的缩写,他们是:Aho、(Peter)Weinberg和(Brain)Kernighan。awk是一个优秀的样式扫描与处理工具。awk提供了极其强大的功能:它几乎可以完成grep和sed所能完成的全部工作,同时,它还可以可以进行样式装入、流控制、数学运算符、进程控制语句甚至于内置的变量和函数。它具备了一个完整的语言所应具有的几乎所有精美特性。awk 命令可以在命令行输入,也可以写在awk 脚本文件里。要处理的文本行则来自文件、管道或标准输入。
1.基本语法
awk [options] 'program' file file ...
awk [options] 'PATTERN{action}' file file ...
2.从文本输入
2.1下面演示/etc/passwd的文件,用awk打印出含有root的行




2.2当打印文件/etc/passwd的某一行含有模式root时,打印改行的1.3两个字段



3.从命令输入
可以将一条或多条linux命令的输出通过管道发给awk处理。格式如下:




4.awk的变量:内置变量和自定义变量

4.1内置变量
FS:Field Seperator, 输入时的字段分隔符

RS:Record Seperator, 输入行分隔符

OFS: Output Field Seperator, 输出时的字段分隔符

ORS: Outpput Row Seperator, 输出时的行分隔符

NF:Numbers of Field,字段数

NR:Numbers of Record, 行数;所有文件的一并计数

FNR:行数;各文件分别计数

ARGV:数组,保存命令本身这个字符

ARGC: 保存awk命令中参数的个数

FILENAME: awk正在处理的当前文件的名称

4.2可自定义变量
-v var_name=VALUE

可以program中定义变量;

可以命令行中通过-v选项自定义变量;

变量名区分字符大小写;

5.print函数
也可以用{print}形式在awk命令的动作部分显式地调用print函数。print函数的参数可以是变量、数值或字符串常量。字符串必须用双引号括起来。参数之间用逗号分隔,如果没有逗号,所有的参数就会被串在一起。默认情况下是空格逗号等价于OFS中的值.
例.利用date命令输出时间,通过awk截取年份和月份







6.printf函数
printf函数返回一个带格式的字符串给标准输出,如同C语言中的printf语句一样。printf语句包括一个加引号的控制串,控制串中可能嵌有若干格式说明和修饰符。控制串后面跟一个逗号,之后是一列由逗号分隔的表达式。printf函数根据控制串中的说明编排这些表达式的格式。与print函数不同的是, printf不会在行尾自动换行。因此,如果要换行,就必须在控制串中提供转义字符\n。



下面通过一个实例来看



对于echo命令的输出,Linux是经管道发给awk。printf函数包含一个控制串。百分号让printf做好准备,它要打印一个占15个格、向左对齐的字符串,这个字符串夹在两个竖杠之间,并且以换行符结尾。百分号后的短划线表示左对齐。
7.字段分隔符
输入字段分隔符awk的内存变量FS中保存了输入字段分隔符的值。使用FS的默认值时,awk用空格或制表符来分隔字段,并且删除各字段前多余的空格或制表符。



虽然前面-F有指定分隔符:,但是后面通过赋值给变量OFS将其覆盖了。也就是说我们可以通过OFS这个变量来定义分隔符。
8.awk关系运算符

下表列出了所有关系运算符。关系表达式的计算结果为真时,表达式的值为1;反之,则为0。
运算符 含义
< 小于
<= 小于等于
== 等于
!= 不等于
>= 大于等于
> 大于
~ 与正则表达式匹配
!~ 与正则表达式不匹配
9.算术运算
运算符 含义
+ 加
- 减
* 乘
/ 除
% 模
^ 幂
10.逻辑运算
运算符 含义
&& 与
|| 或
! 非
11.awk的BEGIN与END模式

BEGIN模式后面跟了一个操作块。awk命令必须在对输入文件进行任何处理之前先执行该操作块。实际上,不需要任何输入文件,也能对BEGIN块进行测试,因为awk要在执行完BEGIN操作块后才开始读取输入。BEGIN操作常常被用于修改 内存变量(OFS、RS、FS等)的值、为 用户自定义变量赋初值和打印输出的页眉或标题。



说明在处理输入文件之前,awk先把(FS)设为冒号,把输出分隔符(OFS)设为制表符,还把输出记录分隔符(ORS)设为两个换行符。如果BEGIN的操作块中有两条或两条以上语句,必须用分号分隔它们或每行只写一条语句(在shell的命令提示符下输入时,必须用反斜杠来转义换行符)。

[root@lys ~]# awk 'BEGIN{print "MAKE YEAR"}'
MAKE YEAR
awk将显示MAKE YEAR。awk打开输入文件之前先执行该print函数,即使没有指定输入文件,awk也照样打印MAKE和YEAR。END模式不匹配任何输入行,而是执行任联何与之关的操作。awk处理完所有输入行之后才处理END模式。例:
[root@lys ~]# awk 'END{print "The number of record is " NR}' /etc/fstab
The number of record is 13
awk处理完整个文件后才开始执行END块。此时NR的值是最后这条记录的记录号
[root@lys ~]# awk '/UUID/{count++}END{print "UUID was found " count " times."}' /etc/fstab
UUID was found 5 times.
每遇到一个包含模式Mary的行,用户自定义的变量counter的值就加1.
12.输出重定向

[root@lys ~]# awk '$4 >= 70 {print $1,$2 > "passing_file"}' /etc/ssh/
如果记录的第4个字段的值大于或等于70,它的头两个字段就被打印到文件passing_ file 中。
13.awk if 语句
[root@lys ~]# awk '{if($6 > 50) print $1 "Too high"}' /etc/grub2.cfg
#Too high
#Too high
#Too high
ifToo high
ifToo high
ifToo high
ifToo high
ifToo high
ifToo high
#Too high
menuentryToo high
ifToo high
linux16Too high
menuentryToo high
ifToo high
linux16Too high
#Too high
#Too high
#Too high
ifToo high
在if操作块中对表达式进行测试。如果第6个字段的值大于50,就执行打印语句。
14.if else 语句

[root@lys ~]# awk '{if($6 > 50) {count++;print $3;} else {x+5;print $2;}}' /etc/grub2.cfg
NOT

is

/etc/grub.d
BEGIN

pager=1
-s

如果第一个表达式为真,即第6个字段($6)的值大于50,则执行表达式后面的这个语句块。否则就执行else后面的那个语句块。注意,语句块必须括在花括号中。

15.awk循环

[root@lys ~]# awk '{i=1; while(i<=NF){print NF,$i; i++ }}' /etc/passwd
1 root:x:0:0:root:/root:/bin/bash
1 bin:x:1:1:bin:/bin:/sbin/nologin
1 daemon:x:2:2:daemon:/sbin:/sbin/nologin
1 adm:x:3:4:adm:/var/adm:/sbin/nologin
1 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
1 sync:x:5:0:sync:/sbin:/bin/sync
1 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
1 halt:x:7:0:halt:/sbin:/sbin/halt
1 mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
1 operator:x:11:0:operator:/root:/sbin/nologin
1 games:x:12:100:games:/usr/games:/sbin/nologin
2 ftp:x:14:50:FTP
以上只是部分输出,变量i被初始化为1 ;当i小于或等于记录的字段数(NF)时,先执行print语句,然后将i加1。接下来又重新测试表达式,直至i大于NF的值。变量i要在awk开始处理下一条记录时被重置。

16.for循环

[root@lys ~]# awk '{for(i=1;i<=NF;i++) print NF,$i}' /etc/passwd
1 root:x:0:0:root:/root:/bin/bash
1 bin:x:1:1:bin:/bin:/sbin/nologin
1 daemon:x:2:2:daemon:/sbin:/sbin/nologin
1 adm:x:3:4:adm:/var/adm:/sbin/nologin
1 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
1 sync:x:5:0:sync:/sbin:/bin/sync
1 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
1 halt:x:7:0:halt:/sbin:/sbin/halt
1 mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
1 operator:x:11:0:operator:/root:/sbin/nologin
1 games:x:12:100:games:/usr/games:/sbin/nologin
变量i被初始化为1 ;当i小于或等于记录的字段数(NF)时,先执行print语句,然后将i加1。接下来又重新测试表达式,直至i大于NF的值。变量i要在awk开始处理下一条记录时被重置。
17.next:提前结束对本行的处理进而提前进入下一行的处理

[root@lys ~]# awk -F: '{if($3%2==0) next;print $1,$3}' /etc/passwd
bin 1
adm 3
sync 5
halt 7
operator 11
nobody 99
dbus 81
abrt 173
polkitd 999
tss 59
postfix 89
chrony 997
以上语句意义是如果第三个字段的值是偶数,则跳过,并打印1,3字段
18.awk数组:数组在awk中被称为关联数组(associative arrays) ,因为它的下标既可以是数字也可以是字符串。下标通常又被称作键(key),并且与对应的数组元素的值相关联。数组元素的键和值都存储在awk程序内部的一个表中,该表采用的是散列算法。
[root@lys ~]# awk -F : '{id[NR]=$3}END{for(x=1; x<=NR; x++){print id[x]}}' /etc/passwd
0
1
2
3
4
5
6
7
awk变量NR保存当前记录的记录号。本例用NR作为下标,把每条记录的第3个字段赋值给数组中的相应元素。最后,for循环对数组进行循环处理,打印出保存在数组中的值。
19.split与delete函数: awk的内置函数split能够将字符串拆分为词,然后保存在数组中。您可以指定字段分隔符,也可以就用FS的当前值
格式:
split (字符串,数组,字段分隔符)
split (字符串,数组)
[root@lys ~]# netstat -tn | awk '/^tcp/{lens=split($5,client,":");ip[client[1]]++}END{for (i in ip) print i,ip[i]}'
192.168.2.107 3
delete函数用于删除数组元素

awk '{line[x++]=$2}END{for(x in line) delete(line[x])}' /etc/passwd
赋给数组line的值是第2个字段的值。所存记录都处理完后,特殊for循环将遍历数组的所有元素,并由delete函数来删除它们。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  linux sed awk