SDB:Sed和AWK

跳转至: 导航, 搜索
介绍一些Sed和AWK的简单使用

定义

  • Sed : 处理纯文本流的文本编辑器。
  • AWK : 一种输出格式化语言。

起先不用过分纠结于概念,实践几次以后就会有点体会了。越多的使用它就会对它理解的更深。现在不妨先跳过它。回头再来看这个定义。

Sed

Sed可以用来处理文件,我们来举个实际的例子。

首先我们来创建两个文件,随便用什么工具,Kate啊,vim啊,gvim啊都可以,如果你在学习vim正好这也是个应用的机会。

下面我用touch,echo和重tee来创建两个文件,这样做没什么方便的,纯粹就是为了熟悉命令。


首先创建三个个空文件。

touch one.txt two.txt three.txt

给两个空文件分别加入内容

echo -e "a\nb\nc\nd\n" | tee ./one.txt

echo是终端打印的命令,-e选项是说在字符中会使用到转义符号,就是这里的\n了,学过c的同学知道它和c是一样的。甚至你可以这样

printf "d\ne\nf\ng\n" | tee ./two.txt

这就和c更像了。上面的命令可以把内容加入two这个文件中。其中|是通道,将echo和printf的输出传递给tee,而tee的作用是,不仅在终端打印数据,还会把数据输送到文件。如果希望添加而不是不是覆盖可以加上选项 -a

echo -e "a\nb\nc\nd\n" | tee -a ./two.txt


然后我们使用下面命令

sed -e s/a/z/g one.txt two.txt > three.txt 


你可以用cat来查看内容

cat ./three.txt

输出如下

z
b
c
d
d
e
f
g


我们可以这样理解sed,它把指定的一些文件或输入用一组命令来处理,然后输出到标准输出中。

在这里,指定的文件就是one.txt 和two.txt,而处理的命令就是 s/a/z/g,标准输出就是终端输出,在这里我们通过重定向将它定向到了一个文件里。

我们来看看这个命令,熟悉vim的同学会发现它和vim是一样的,就是搜索和替换,就是把a替换成z,/g的意思是整行的替换,去掉这个只会替换在一行里找到的第一个。当然,在这个例子里是没有影响的。


其实sed的命令可以有多个,比如

sed -e 's/a/z/g; s/b/y/g' one.txt two.txt > three.txt

再用cat看看输出,发现了么,这里的用把命令扩起来,用分号分割不同的命令,其实,只有一个命令的时候也建议你用,这样可以更清楚。


sed还可以多行记录

sed '
>s/a/z/
>s/b/y/ ' one.txt two.txt


其实sed最方便的还是可以把命令写进文件里,这样就可以重复利用,不用每次都敲那么多代码了。

创建一个文件,这次我们用vim好了

vim edits.sedscr
s/a/z/
s/b/y/


然后sed -f edits.sedscr one.txt two.txt > three.txt


AWK

AWK的用法和sed其实非常的相似。同样的,他是输入一个命令或一组命令或是写着命令的文件,以及数据或写着数据的文件。然后格式化后输出。

我们来举个实际点的例子。比如我们要提取/etc/passwd里的信息,我们知道这个文件里储存的是用户的资料,电脑通过字段可以很轻松的识别,可是对于系统的管理者来说就没那么方便了,本身记忆那么多字段也是一种负担,现在我们就通过awk来处理这些信息使其变得清晰。


注意此命令要在root后实用,不是所有人都有权限查看/etc/passwd文件的。

#awk -F":" '{print "usrename:" $1 "\t\t\t user ID:" $3}' /etc/passwd

下面是我的部分输出。

usrename:at                      user ID:25
usrename:avahi                   user ID:487
usrename:bin                     user ID:1
usrename:daemon                  user ID:2
usrename:dhcpd                   user ID:491
usrename:dnsmasq                         user ID:488
usrename:fetchmail                       user ID:481
usrename:ftp                     user ID:40
usrename:ftpsecure                       user ID:482
usrename:games                   user ID:12
usrename:gdm                     user ID:480

同样的被扩起来的是命令,其中我们知道在passwd文件中第一个字段是用户名,第三个字段是用户ID,默认awk是以空格作为划分字段的依据的。使用了 -F":"后就改成了以:作为划分的依据了。

同样的AWK的命令可以写进文件

vim print.awk
BEGIN{
    FS=":"
    }
    {printf "\nusername:" $1 "\t\t\t user ID:" $3}
END{
    printf "\ndone\n"
    }
   

然后运行

awk -f print.awd /etc/passwd

你可以看到和上面差不多的输出,其中BEGIN和END的内容只会被执行一次,在这个例子中END的用途只是打印了一个done,告诉你已经执行完成了。 你完全可以去掉它。


与正则表达式结合

但是很多时候并不那么简单,比如,分隔符也许非常的多样,有时虽然机器的输出是格式化的,但是也需要一些智慧去分析,很多时候它会和正则表达式结合,在这里只举一个简单的例子。假设/etc/passwd分隔符有:和,两种(当然这不是真的)。这个时候你可以这样

#awk -F"[:,]" '{print "usrename:" $1 "\t\t\t user ID:" $3}' /etc/passwd

从这个例子你可以窥见,AWK可以编写很复杂的命令来处理复杂的数据,这也许就是为什么我们会说编写AWK程序了。有时它确实就像是一个程序。

关于正则表达式的内容请参看相关的wiki。