|
第十二章 sed和awk介绍 翻译:hfzheng hfzheng@sohu.com 转载请保留此信息 流编辑器 sed程序(或流编辑器)用于编辑文件中的数据,而无须使用交互式编辑器如vi打开。你可以在命令行方式下对一个文件进行编辑和修改,默认情况下,输出送到屏幕上。可以快速完成重复工作。 Sed编辑器不改变源文件的内容,要保存输出,需要重定向到一个新文件中。 该编辑器最常用于对多个文件做相同的修改,也用于阅读管理员需要的脚本。 命令格式 sed [options] [address] command files [>newfile] sed命令也可以用在管道中,例如: ls –l | sed 选项(options): 选项用于控制sed的行为,最常用的选项是: 1、-e:允许在同一命令行进行多个编辑; 正则表达式概述 和grep命令相类似,sed使用许多特殊元字符来控制搜索模式。 下面描述了sed中使用的有用的正则表达式的元字符: 元字符目的 示例 结果 ^行开始标识符‘^pattern’匹配所有以pattern开头的行 $行结束标识符‘pattern$’匹配所有以pattern结束的行 .匹配一个字符‘p…..n’匹配所有包含有以p开头后跟五个字符,紧接着跟一个字符的行 *[a-z]*匹配小写字符 []匹配模式中的单个字符‘[pP]attern’匹配包括pattern和Pattern模式的行 [^]匹配不在模式中单个字符‘[a^m]attern’匹配以a到m结尾attern的所有行 其他说明同grep命令。 使用流编辑器 使用d命令删除一行 下面的例子显示了sed如何搜索包含有指定pattern的行,并删除改这些行。 1、在文件中搜索指定模式,并删除所有包含该模式的行,源文件不会被修改: sed ‘/pattern/d’ filename 例如从文件/etc/group中删除所有包含了模式root的行: $ sed ‘/root/d’ /etc/group 下例显示了如何删除ls命令的输出中包含有3的行: $ ls –l | sed ‘/3/d’ 2、删除文件中的指定行,结果显示在屏幕上,源文件不会被修改: sed ‘#,#d’ filename(删除行#到行#) sed ‘#d’ filename(只是删除行#) sed ‘#,$d’ filename(删除行#直到最后一行) sed ‘$d’ filename(只删除最后一行) 例如: $ ls –l | sed ‘5, $d’ > new.file $ cat new.file 使用p命令打印行 默认情况下,sed打印所有行到标准输出,如果找到模式pattern,sed在输出中打印重复行,至于文件中的其他行,直接输出。 $ sed ‘/Dante/p’ dante 在上例中,默认情况下,sed打印所有的行到标准输出,如果找到模式Dante,sed在输出中打印重复行,文件中的其他行直接输出。 使用-n选项可以抑制带p命令的sed的默认操作,例如: $ sed –n ‘/Dante/p’ dante 在上例中,只打印包含有模式Dante的行 在每行的结尾放置字符 下面的示例显示了如何在行结尾添加字符。 要在每行的结尾添加字符串并把结果显示在标准输出中,执行下面的命令: $ ls –l | sed ‘s/$/ EOF/’ 修改数据中的空格为冒号 要搜索一个或多个空格,并用一个冒号来代替所有发现的空格,执行以下命令: $ ls –l | sed ‘s/ */:/g’ sed多编辑 下面显示了sed在同一命令行中如何实现多编辑 $ ls –l > file.3 $ cat file.3 $ sed –e ‘s/dante/DANTE/g’ –e ‘s/poet/Poet/g’ filename 在上例中,创建了一个新文件,sed执行了两个带-e选项的命令,第一个命令为替换所有的小写dante为大写DANTE,第二个命令为在字Poet后添加poet,并显示结果到标准输出。 使用awk进行文本处理 awk为一个文本处理器,用于操作列数据并产生报表,awk从第一行到最后一行逐行扫描文件,搜索包含有指定模式的行,并对这些行执行选定的操作。 awk的基本应用包括对数据进行格式更改、重新安排列、添加文本。 命令格式 awk ‘{action}’ filename 基本awk命令格式 基本的awk命令格式包括awk命令、用引号和大括号括起来的指令、输入文件名称,如果没有指定输入文件名,使用标准输入,例如,键盘。 下面为一个基本awk命令,ls –l的命令的输出用管道送到awk中,awk接收到的每一个行,执行打印动作,输出结果到屏幕: $ ls –l | awk ‘{print $0}’ 上面命令的结果和ls –l命令的输出一样: -rw-r-r-- 1 user2 other 1409 Jun 2 16:14 date.file $1 $2 $3 $4 $5 $6 $7 $8 $9 $0 基本awk命令的结果 awk读取每一行时,自动把行分成不同的域,每一行赋予一个变量名,空格或者tab键作为默认的域分隔符。 赋予每个域的变量名为一个美元符号后跟一个域数字,从左到右计数。变量名$1代表第一个域的内容,$2代表第二个域的内容,依此类推。$0代表整个行。 使用awk来显示指定数据 要告诉awk显示指定的数据,例如文件所有者、文件大小、文件名称,需要使用域名称。 $ ls –l | awk ‘{print $3 $5 $9 }’ user10beans.backup user154120dante user1368dante_1 user1176dat user1512dir1 user1512dir2 user1512dir3 user1512dir4 user1592148file.1 user10file.txt user1235file1 user1105file2 user1218file3 user1137file4 user135file5 user1715files.tar.Z user156fruit user157fruit2 user12483logfile user10nuts user1512practice root512public_directory user131script1 user140script2 user122script3 user156script6 user1512shared_directory user111603text.file.Z user128738tutor.vi $ 上例输出的三个域之间没有空格。 下面告诉awk来输出域之间加上空格: $ ls –l | awk ‘{print $3 ,$5, $9 }’ user1 0 beans.backup user1 54120 dante user1 368 dante_1 user1 176 dat user1 512 dir1 user1 512 dir2 user1 512 dir3 user1 512 dir4 user1 592148 file.1 user1 0 file.txt user1 235 file1 user1 105 file2 user1 218 file3 user1 137 file4 user1 35 file5 user1 715 files.tar.Z user1 56 fruit user1 57 fruit2 user1 2483 logfile user1 0 nuts user1 512 practice root 512 public_directory user1 31 script1 user1 40 script2 user1 22 script3 user1 56 script6 user1 512 shared_directory user1 11603 text.file.Z user1 28738 tutor.vi $ 上例上,一个输出的域之间加上了空格,不过,域并不对齐。 要使得输出的域对齐,在双引号“”之间放入tab键对应的空格。 $ ls –l | awk ‘{print $3 “ ” $5”” $9 }’ user1 0 beans.backup user1 54120 dante user1 368 dante_1 user1 176 dat user1 512 dir1 user1 512 dir2 user1 512 dir3 user1 512 dir4 user1 592148 file.1 user1 0 file.txt user1 235 file1 user1 105 file2 user1 218 file3 user1 137 file4 user1 35 file5 user1 715 files.tar.Z user1 56 fruit user1 57 fruit2 user1 2483 logfile user1 0 nuts user1 512 practice root 512 public_directory user1 31 script1 user1 40 script2 user1 22 script3 user1 56 script6 user1 512 shared_directory user1 11603 text.file.Z user1 28738 tutor.vi $ 使用awk来改变数据格式 可以告诉awk命令来重新排列数据。 要格式化数据,把文件名称放在第一,然后文件大小,最后是文件所有者: $ ls –l | awk ‘{print $9,$5, $3}’ beans.backup 0 user1 dante 54120 user1 dante_1 368 user1 dat 176 user1 dir1 512 user1 dir2 512 user1 dir3 512 user1 dir4 512 user1 file.1 592148 user1 file.txt 0 user1 file1 235 user1 file2 105 user1 file3 218 user1 file4 137 user1 file5 35 user1 files.tar.Z 715 user1 fruit 56 user1 fruit2 57 user1 logfile 2483 user1 nuts 0 user1 practice 512 user1 public_directory 512 root script1 31 user1 script2 40 user1 script3 22 user1 script6 56 user1 shared_directory 512 user1 text.file.Z 11603 user1 tutor.vi 28738 user1 $ 格式化数据显示文件所有者、文件名、文件创建和修改日期并对齐域: $ ls –l | awk ‘{print $3 “” $9 “” $6, $7}’ user1 beans.backup May 1 user1 dante Apr 16 user1 dante_1 Mar 22 user1 dat May 2 user1 dir1 May 1 user1 dir2 Mar 22 user1 dir3 Mar 22 user1 dir4 Mar 22 user1 file.1 May 1 user1 file.txt Apr 12 user1 file1 May 1 user1 file2 Mar 22 user1 file3 Mar 22 user1 file4 Mar 22 user1 file5 Mar 22 user1 files.tar.Z May 1 user1 fruit Mar 22 user1 fruit2 Mar 22 user1 logfile May 1 user1 nuts May 1 user1 practice Mar 22 root public_directory Mar 31 user1 script1 Apr 15 user1 script2 Apr 15 user1 script3 May 1 user1 script6 Mar 31 user1 shared_directory Mar 31 user1 text.file.Z May 1 user1 tutor.vi Mar 22 $ 使用awk增加文本 awk命令可以用于重新安排数据格式,也可以在域之间增加新文本。 $ ls –l | awk ‘{print $9,”is using”, $5,”bytes”}’ file1 is using 405 bytes file2 is using 66 bytes file3 is using 66 bytes file4 is using 66 bytes file5 is using 46598 bytes file6 is using 1409 bytes $ 当在命令行中使用awk命令增加文本时,增加的文本要用双引号括起来,除了最后一个增加的文本之外,在引号后都要加逗号。如上所示。
|