当前位置: 首页 > Linux

Linux三剑客awk、grep、sed详解

时间:2023-04-06 20:42:19 Linux

前言Linux有很多文本处理的工具,比如:sort,cut,split,join,paste,comm,uniq,column,rev,tac,tr,nl,pr,head,tail.......,学习linux文本处理的偷懒方法(不是最好的方法)可能是:只学grep、sed和awk。使用这三个工具,你可以解决近99%的linux系统的文本处理问题,而无需记住上面不同的命令和参数。而且,如果您已经学习并使用了这三者,您就会知道其中的区别。在实践中,这里的差异意味着哪种工具擅长解决哪些问题。一种更懒惰的方法可能是学习一种脚本语言(python、perl或ruby??)并将其用于每个文本处理。概述awk、grep、sed是linux操作文本的三大利器,也是必须掌握的linux命令之一。三者的作用都是处理文本,只是侧重点不同。其中,awk是最强大的,但也是最复杂的。grep更适合简单的搜索或匹配文本,sed更适合编辑匹配的文本,awk更适合格式化文本,对文本进行更复杂的格式化。小结:grep:数据查找定位awk:数据切片sed:数据修改grep=globalregularexpressionprint最简单的来说,grep(globalregularexpressionprint)--命令用于在文件中查找满足条件的字符串.从文件的第一行开始,grep将一行复制到缓冲区中,将其与搜索字符串进行比较,如果比较通过则将该行打印到屏幕上。grep将重复此过程,直到文件搜索所有行。注意:这里没有执行grep来存储行、更改行或仅搜索部分行的过程。示例数据文件将以下数据剪切并粘贴到名为“sampler.log”的文件中:文件“sampler.log”并打印出其中的每一行都包含单词“boo”:bootbookboozeboots但如果您正在处理大文件,情况就是这样:如果这些行标识了哪一行,它们是什么,可能更多对您很有用,如果您需要在编辑器中打开文件,可以更轻松地跟踪特定字符串以进行一些更改。这可以通过添加-n参数来实现:grep-n"boo"sampler.log这会产生一个更有用的结果,解释哪些行与搜索字符串匹配:1:boot2:book3:booze5:bootsanother有趣的参数是-v,它打印相反的内容。换句话说,grep将打印所有与搜索字符串不匹配的行,而不是打印匹配它的行。grep将打印不包含带有行号的字符串“boo”的每一行,如前面的示例grep-vn"boo"sampler.log4:machine6:bungie7:bark8:aardvark9:broken$tuff10:robotsc选项告诉grep禁止打印匹配行,只显示匹配行数,即匹配查询的行。例如,以下将打印数字4,因为在sampler.log中出现了4次“boo”。grep-c"boo"sampler.log4l选项仅打印查询中具有与搜索匹配的行的文件的文件名字符串。如果您想在多个文件中搜索相同的字符串,这很有用。像这样:grep-l"boo"*对于搜索非代码文件,一个更有用的选项是-i,忽略大小写。此选项将在匹配搜索字符串时处理大小写相等性。在下面的示例中,即使搜索字符串是大写的,也会打印包含“boo”的行。grep-i"BOO"sampler.logbootbookboozebootsx选项仅完全匹配。换句话说,下面的命令搜索不到任何结果,因为没有只包含“boo”的行搜索字符串额外的行,例如grep-A2"mach"sampler.logmachinebootsbungie正则表达式正则表达式是描述文本中复杂模式的紧凑方式。通过grep,您可以使用搜索模式(pattern)。其他工具以复杂的方式使用正则表达式(regexp)。grep使用的普通字符串实际上是非常简单的正则表达式。如果您使用通配符,例如“*”或“?',例如列出文件名等,可以使用grep使用基本的正则表达式进行搜索,例如搜索以字母e结尾的行:grep"e$"sampler。logboozmachinebungie必须使用grep-E如果你想要更广泛的正则表达式命令。例如,正则表达式命令?将匹配前面字符出现1次或0次:grep-E"boots?"sampler.logbootboots你也可以用管道符(|)组合多个搜索,意思是“或”,所以你可以这样做:grep-E"boot|boots"sampler.logbootbootsspecialcharacters如果你想搜索什么for是一个特殊字符?如果你想找到包含美元字符“$”的所有行,那么你不能做grep"$"a_file因为'$'将被解释为正则表达式,相反你会得到所有包含任何行的行结尾,即所有行。解决方案是“转义”符号,因此您可以使用grep'$'sampler.logbroken$tuff您还可以使用代表“固定字符串”或“快速”的“-F”选项,因为它只搜索字符串,而不搜索正则表达式。有关更多正则表达式示例,请参见:http://gnosis.cx/publish/prog...AWK由Aho、Weinberger和Kernighan创建的一种文本模式扫描和处理语言。AWK非常复杂,因此这不是一个完整的指南,但应该让您了解awk可以做什么。使用起来比较简单,强烈推荐。AWK基础awk程序对输入文件的每一行进行操作。它可以有一个可选的BEGIN{}部分,用于在处理文件的任何内容之前执行命令,然后是在文件的每一行上运行的主要{}部分,最后是一个可选的END{}部分,其中操作将跟随执行文件读取完成:BEGIN{....初始化awk命令...}{....文件每一行的awk命令...}END{....完成awk命令...}对于文件的每一行输入文件,它查看是否有任何A模式匹配指令,在这种情况下它只对匹配模式的行进行操作,否则它对所有行进行操作。这些“模式匹配”命令可以包含像grep这样的正则表达式。awk命令可以进行一些非常复杂的数学运算和字符串操作,awk还支持关联数组。AWK将每一行视为由多个字段组成,每个字段由“间隔符”分隔。默认情况下这是一个或多个空格字符,所以行:这是包含6个字段的文本行。在awk中,第一个字段称为$1,第二个字段称为$2,依此类推,整行称为$0。字段分隔符由awk内部变量FS设置,所以如果你设置FS=":"那么它会根据':'的位置分割一行,这对于/etc/passwd这样的文件很有用,其他有用内部变量是NR,当前记录号(即行号)NF是当前行的字段数。AWK可以对任何文件进行操作,包括std-in,在这种情况下它通常与'|'一起使用命令,例如结合grep或其他命令。例如,如果我列出当前目录中的所有文件ls-ltotalusage140-rw-r--r--1rootroot5512Nov317:03combined_log_format.log-rw-r--r--1rootroot806441317:03combined_log_format_w_resp_time.log-rw-r--r--1rootroot711317:55sampler.log`我可以看到报告为3列数据的文件大小。如果我想知道它们的总大小,这个目录中的文件我可以这样做:ls-l|awk'BEGIN{sum=0}{sum=sum+$5}END{printsum}'135836注意,'printsum'打印变量sum的值,因此如果sum=2则'printsum'给出输出'2'而'print$sum'将打印'1',因为第二个字段包含值'1'。因此,编写一个计算数字列表的均值和标准差的awk命令是微不足道的——在main中累加“sumx”和“sumx2”部分,然后使用标准公式计算均值和标准差END部分。AWK支持(“for”和“while”)循环和分支(使用“if”)。所以,如果你想修剪一个文件并且只对每3行进行操作,你可以这样做:ls-l|awk'{for(i=1;i<3;i++){getline};打印NR,$0}'3-rw-r--r--1rootroot80644Jan317:03combined_log_format_w_resp_time.log4-rw-r--r--1rootroot71Jan317:55sampler.logsampler.logforloop使用“getline”命令遍历文件并且每3次只打印一行。注意,由于文件的行数是4,不能被3整除,所以最后一个命令提前完成,所以最后的“print$0”命令打印第4行,可以看到我们也打印了这一行,使用NR变量输出行号。AWK模式匹配AWK是一种面向行的语言。首先是模式,然后是动作。动作语句包含在{和}中。可能会缺少模式,或者可能会缺少操作,但当然不会两者兼而有之。如果模式缺失,则对每个输入记录执行操作。缺少的操作将打印整个记录。AWK模式包括正则表达式(使用与“grep-E”相同的语法)和使用特殊符号“&&”表示“逻辑与”、“||”的组合对于“逻辑或”,和“!”对于“逻辑否”。您还可以执行关系模式、模式组、范围等。AWKcontrolstatementif(condition)statement[elsestatement]while(condition)statementdostatementwhile(condition)for(expr1;expr2;expr3)statementfor(varinarray)statementbreakcontinueexit[expression]AWKinput/output注:printf命令允许您使用类似C的语法来更精确地指定输出格式。例如,您可以指定整数、浮点数或给定宽度的字符串等。AWK数学函数AWK字符串函数AWK命令行和用法awk程序,例如awk-vskip=3'{for(i=1;inew_filesed-i-e's/input/output/'sampler.logsed和正则表达式如果您想在搜索命令中使用的字符之一是像“/”这样的特殊符号怎么办?(例如在文件名中)或“*”等?然后你必须转义像grep(和awk)这样的符号。假设您想编辑shell脚本以引用/usr/local/bin而不是/bin,那么您可以执行sed-e's//bin//usr/local/bin/'my_script>new_script如果您想要搜索中的通配符怎么办——输出字符串怎么写?您需要使用与找到的模式对应的特殊符号“&”。因此,假设您希望文件中的每一行都以一个数字开头,并用方括号括住该数字:sed-e's/[0-9]*/(&)/'其中[0-9]是所有数字正则表达式的数字范围,而'*'是重复计数,表示任何数字的位数。您还可以在正则表达式中使用位置指令,甚至可以将部分匹配保存在模式缓冲区中以供在其他地方重用。其他SED命令的一般形式是sed-e'/pattern/command'sampler.log其中'pattern'是正则表达式,'command'可以是's'=search&replace,或'p'=print,或'd'=delete或'i'=insert或'a'=append等。请注意,默认操作是打印所有不匹配的内容,因此如果你想抑制它,你需要使用'-调用sedn'标志,然后你可以使用'p'命令来控制打印的内容。所以如果你想做一个所有子目录的列表,你可以使用ls-l|sed-n-e'/^d/p'因为长列表如果是目录则每一行都以'd'符号开头,所以这只会打印出那些以'd'符号开头的行。同样,如果要删除所有以注释符号“#”开头的行,可以使用sed-e'/^#/d'sampler.log或使用范围形式sed-e'1,100command'sampler。登录第1-100行执行“命令”。您还可以使用特殊行号$来“结束”文件。所以如果你想删除除文件的前10行之外的所有行,你可以使用sed-e'11,$d'sampler.log你也可以使用模式范围形式,其中第一个正则表达式定义范围的开始,第二站。因此,例如,如果您想打印从“boot”到“machine”的所有行,您可以这样做:sed-n-e'/boot$/,/mach/p'sampler.logbootbookboozmachine然后打印出来(-n)正则表达式给定范围内的那些行的正则表达式。延伸阅读sed可以做很多事情。详见:http://www.grymoire.com/Unix/...Linux三剑客总结awk、sed、grep广泛应用于性能建模、性能监控和性能分析也是高频面试各大互联网公司试岗题,中高端测试人员必备技能之一