当前位置: 首页 > Linux

编程技巧Linux文本处理命令

时间:2023-04-07 01:41:35 Linux

合格的程序员善于使用工具。合理使用Linux命令行工具可以提高我们的工作效率。本文简单介绍三种使用Linux文本处理命令的场景,开阔你的思路。希望大家看完这篇文章,多多练习,将这些技巧内化到日常的工作习惯中,真正提高效率。内化很重要,就像一句笑话说的,即使我知道高内聚低耦合的要求,了解23种设计模式和6条原则,熟悉cleancode之道,我还是写不出优秀的代码.知道和内化为行为之间还是有很大区别的。能不能让正确的原则指导正确的行动本身,其实就是区分高手与否的一个显着标志。程序员在日常工作中经常要处理一些数据和文本,比如统计一些服务日志文件信息,生成一些SQL进行数据处理,根据数据库数据查找文件内容等。可以直接写代码处理,但是不够方便,因为有时候网上相关的代码环境依赖可能没有。直接使用Linux的文本处理命令来处理这些问题是非常方便的。从日志文件中收集数据在工作中,我们经常需要对一些固定格式的文件进行信息统计。比如根据nginx的access.log文件数据,计算出各个后端API接口的调用次数,并进行排序。nginx的access.log文件的文件格式配置如下,各个字段用空格隔开。log_formatmain'$remote_addr-$remote_user[$time_local]"$request"''$status$body_bytes_sent"$http_referer"''"$http_user_agent""$http_x_forwarded_for"';上述配置中各字段含义如下:$remote_addr:发送请求的源地址$remote_user:发送请求的用户信息$time_local:接收请求的本地时间$request:请求信息,如http的方法和路径。$status:请求状态,例如200、401或500。$body_bytes_sent:请求正文字节。$http_referer:域名。$http_user_agent:客户端代理信息,一般为浏览器信息$http_x_forwarded_for:其他信息。access.log的一段具体内容如下。58.213.85.34--[11/Sep/2019:03:36:11+0800]"POST/publish/pending/listHTTP/2.0"2001328"https://remcarpediem.com/""Mozilla/5.0(Macintosh;IntelMacOSX10_14_5)AppleWebKit/537.36(KHTML,likeGecko)Chrome/75.0.3770.142Safari/537.36"58.213.85.34--[11/Sep/2019:03:36:30+0800]"GET/publish/search_inner?key=testHTTP/2.0"20034466"https://remcarpediem.com/""Mozilla/5.0(Macintosh;IntelMacOSX10_14_5)AppleWebKit/537.36(KHTML,likeGecko)Chrome/75.0.3770.142Safari/537.36"那么我们可以使用如下命令统计所有接口的调用次数,并从大到小排序显示。猫/var/log/nginx/access.log|awk'{print$7}'|awk-F'?''{打印$1}'|排序|uniq-c|sort-nr该命令涉及cat、awk、sort、uniq四个命令行工具及|的含义connector,我们将依次对其用途进行简要说明,有兴趣的同学可以充分理解,自行学习。cat命令是将文件内容打印到标准输出设备,可以是终端也可以是其他文件。例如:cat/var/log/nginx/access.log#打印到终端cat/var/log/nginx/access.log>copy.log#打印到其他文件|命令的标准输出指向第二个命令的标准输入。在这个命令中|symbol将cat命令的输出定向到awk命令的输入。awk是贝尔实验室于1977年开发的一种文本流处理工具,用于对固定格式的文件进行流式处理。比如nginx的access.log文件,它的字段之间用空格隔开,awk就很适合处理这类文件。'{print$7}'是awk的命令声明,意思是打印出变量$7,$7是awk的内置变量,表示用分隔符分隔的第七个文本内容。对于access.log文件,就是$request代表的路径相关的内容。$request的全部内容为POST/publish/pending/listHTTP/2.0,$6对应POST,$7对应/publish/pending/list。awk'{print$7}'Access.log#''是命令语句,后面是要操作的文件,是awk的输入流。但是有时候我们会发现文本内容没有用空格隔开。比如$request的内容可能是/publish/search_inner?key=test。虽然是同一个路径,但是查询的内容不同。我们在统计接口调用量的时候,需要使用部分过滤掉的query。我们可以使用awk的-F命令来指定分隔符。awk-F'?''{print$1}'#/publish/search_inner?key=test可以看做/publish/search_innersort是一个专门用来排序的命令,它有多个参数:-n按值排序,默认是按字符值排序,按值比较10>2但按字符值排序,2>10,因为会先比较字符值,即2>1。-r默认升序,该参数指定倒序排序。-kN指定按第N列排序,默认为第一个值sort-nrAccess.log#按数字倒序排序最后一个命令是uniq,用于消除重复行,或者统计。排序unsort.txt|uniq#去除重复行sortunsort.txt|uniq-c#统计文件中每一行出现的次数,输入格式为[字数][内容]sortunsort.txt|uniq-d#查找重复行例如cat/var/log/nginx/access.log|awk'{print$7}'|awk-F'?''{打印$1}'|排序|uniq-c命令的输出如下,与sort-nr的输入完全一样。5/announcement/pending/list5/announcement/search_inner使用这些指令,我们可以通过access.log统计出很多信息,比如下面的信息(access.log的信息配置不同,不能直接复制)。猫访问.log|awk-F'^A''{if($5==500)print$0}'#查找当前日志文件500错误访问:tail-faccess.log|awk-F'^A''{if($6>1)print$0}'#查找耗时超过1s的慢请求数据库SQL在业务迭代过程中,可能需要使用脚本修改部分数据库数据。这样我们就可以根据一些数据命令生成相应的SQL,这里我们可以使用命令行工具快速生成。比如我们要恢复一系列的订单状态问题,我们需要将它们恢复到正常状态。您现在已经收集了这批订单的信息。oder_idnameinfogood_id100000'Pants''山东'1000100001'Top''江苏'1000100002'Underwear''内蒙古'1000.......100003'Socks''江西'1000那么就可以使用如下命令直接生成相应的SQL语句。猫ErrorOrderIdFile|awk'{print"UPDATEORDERSETstate=0WHEREresource_id="$1}'这里''是awk的命令内容,""是打印出来的明文,所以我们可以把需要补充的SQL命令添加到打印出来。代码信息统计在大公司,每个团队往往会公开自己的接口给其他团队调用,但是随着版本的快速迭代,暴露的接口越来越多,想上游调用者往往不清楚是谁关闭它。哪个部门,不敢轻易关闭或修改。这时候,如果你可以访问整个公司的代码库,你可以使用下面的脚本在项目中搜索接口相关的关键词。笔者所在公司团队中的微服务是通过FeignClient相互调用的,所以这种情况下可以直接搜索FeignClient的函数名对应的文件名。下面是一个bash脚本,统计多个项目中某些关键字的出现次数,并打印出文件名。#!/bin/bashkeyword=$1#将bash命令的第一个参数赋给keywordprefix=`echo$keyword|tr-s'.''|'|sed's/$/|/'`#Processprefixfiles=`findservices-name"*.java"-or-name"*.js"|xargsgrep-il$keyword`#最关键的,在services文件夹中搜索.java或.js的文件名后缀和内容里面有关键字的文件名。if[-z"$files"];thenecho${prefix}0fi#printforfin$files;doecho"$prefix$f"done我们只看最关键的find命令,其他命令如tr或sed,大家可以自行理解和学习。find用于查找文件,可以根据文件名、文件操作权限、文件所有者、文件访问时间等条件进行查找。findservices-name"*.java"-or-name"*.js"#搜索服务文件夹find.-atime7-typef-print#-atime为访问时间,-type为文件类型,区分文件和目录,查找最近7天访问的文件。寻找。-typef-userremcarpediem-print//查找用户remcarpediem拥有的文件find.!-name"*.java"-print#!是负参数,查找所有不以.java结尾的文件。寻找。-typef-name"*.java"-delete#find后可以删除当前目录下的所有java文件find.typef-name"*.java"|xargsrm#上述语句的另一个版本写法xargs命令可以将输入的数据转换为特定命令的命令行参数,例如将多行改为一行等,以及拼接多个命令行,例如find和上面的房间。>lsSentinelgroovy-enginespring-cloud-bus-stream-binder-rocketmqagent-demohashspring-cloud-stream-binder-rabbit>ls|xargs#将ls的输出更改为一行。Sentinelagent-demogroovy-enginehashspring-cloud-bus-stream-binder-rocketmqspring-cloud-stream-binder-rabbit>echo“nameXnameXnameXname”||xargs-dXnamenamename#-d选项可以自定义一个固定的Delimiter,相信你已经了解了xargs的大致功能,根据分隔符将文本拆分成一行,默认的分隔符是回车。最后一个命令是grep,它是一个文本搜索命令,可以在文本内容中搜索关键字。grepremcarpediemfile#记录文件file中带有remcarpediem关键字的行。grep-C10remcarpediemfile#收集文件file中remcarpediem关键字前后10行的内容。猫日志。*|grep“来自”|grep"WHERE">b#找出日志中所有带where条件的SQL查询grep-liremcarpediemfile#忽略大小写,打印出文件名现在大家回头看看这个bash脚本,你有通用的吗了解其执行过程和原理?files=`findservices-name"*.java"-or-name"*.js"|xargsgrep-il$keyword`后记本文简要介绍了程序员在日常工作中可能使用Linux命令的三种场景。大家可以根据自己的实际情况,判断是否需要继续全面详细地学习相关知识。毕竟只有能够应用到实践中,为自己的工作创造价值的技术,才是真正的技术。学习一门技术,必须坚持学以致用的目的。个人博客,欢迎来玩