LinuxShell是一项基本功。由于语法怪异,可读性差,通常用Python等脚本代替。既然是基本功,就需要掌握。毕竟在学习Shell脚本的过程中,还是可以学到很多Linux系统的内容的。Linux脚本高手不是每个人都能做到的,但是使用一些简单的shell来实现一些常用的基本功能还是很有必要的。下面介绍一下Linux下使用Shell处理文本时最常用的工具:find、grep、xargs、sort、uniq、tr、cut、paste、wc、sed、awk;提供的例子和参数都是最常用最实用的;shell脚本我使用的原则是单行写命令,尽量不要超过2行;如果你有更复杂的任务需求,可以考虑python;1.find文件搜索查找txt和pdf文件find.(-name"*.txt"-o-name"*.pdf")-print常规模式查找.txt和pdftxt文本find.!-name"*.txt”-print指定搜索深度,打印出当前目录下的文件(深度为1)ffile/lsymboliclink按时间查找:-atime访问时间(单位是天,分钟单位是-amin,下同)-mtime修改时间(内容被修改)-ctime修改时间(元数据或权限改变)最近7天访问过:find.-atime7-typef-print按大小搜索:wwordkMG查找大于2k的文件find.-typef-size+2k按权限搜索:find.-typef-perm644-print//查找所有具有可执行权限的文件按用户搜索:find.-typef-userweber-print//查找用户weber拥有的文件找到后后续操作删除:删除当前目录下的所有swp文件:find.-typef-名称“*.swp”-删除eexecutionaction(powerfulexec)find.-typef-userroot-execchownweber{};//改变当前目录的所有权为weber注意:{}是一个特殊的字符串,对于每一个匹配的文件,{}都会被替换为相应的文件名;例如:将找到的所有文件复制到另一个目录:find.-typef-mtime+10-name"*.txt"-execcp{}OLD;合并多条命令提示:如果后面需要执行多条命令,可以将多条命令写成一个脚本,在调用-exec时执行脚本;-exec./commands.sh{};-printdelimiterdefault使用''作为文件的分隔符;-print0使用''作为文件的分隔符,这样可以搜索包含空格的文件;2、greptextsearchgrepmatch_pattenfile//默认获取匹配行常用参数-o只输出匹配VS-v只输出没有匹配的文本行-c统计文件包含文本的次数grep-c"text"文件名-n打印匹配行号-i搜索时忽略大小写-l只打印文件名递归搜索多级目录中的文本(程序员最喜欢的代码搜索):grep"class".-R-n匹配多个模式grep-e"class"-e"vitural"filegrep输出文件名作为结束字符:(-z)grep"test"file*-lZ|xargs-0rm3、xargs命令行参数转换xargs可以将输入的数据转换成特定命令的命令行参数;这样,它可以与许多命令结合使用。比如grep,比如find;将多行输出转为单行输出catfile.txt|xargs为多行文本之间的分隔符将单行转为多行输出catsingle.txt|xargs-n3-n:指定每行显示的字段数xargs参数说明-d定义分隔符(多行的分隔符默认为空格)-n指定输出为多行-I{}指定替换字符串,xargs展开时将被替换,当要执行的命令需要多个参数eg:catfile.txt|xargs-I{}./command.sh-p{}-1-0:指定为输入分隔符eg:计算程序行数findsource_dir/-typef-name"*.cpp"-print0|xargs-0wc-l4,sort排序字段说明:-n按数字排序VS-d按字典顺序排序-r逆序排序-kN指定使用第N列排序eg:sort-nrk1data.txtsort-bddata//忽略前导空白字符如空格5、uniq消除重复行消除重复行sortunsort.txt|uniq统计每行在文件中出现的次数sortunsort.txt|uniq-c查找重复行sortunsort.txt|uniq-d可以指定每行要比较的重复内容:-s起始位置-w比较字符个数6,用tr转换一般用法echo12345|tr'0-9''9876543210'//加解密转换,替换对应字符cattext|tr''''//tab转空格tr删除字符catfile|tr-d'0-9'//删除所有数字-ccomplementsetcatfile|tr-c'0-9'//获取文件catfile中的所有数字|tr-d-c'0-9'//删除非数字数据trcompressioncharacterstr-s压缩文本中出现的重复字符;最常用于压缩catfile中的冗余字符空间|tr-s''字符类tr中提供了各种字符类:alnum:字母和数字alpha:字母digit:数字space:空白字符lower:小写upper:大写cntrl:控制(不可打印)字符print:可打印字符如何使用:tr[:class:][:class:]eg:tr'[:lower:]''[:upper:]'7、将文本按列切分,截取文件的第二列和第4列:cut-f2,4文件名删除文件除第三列以外的所有列:cut-f3--complementfilename-d指定分隔符:cat-f2-d";"filenamecut取范围N-第N个字段到结尾-M第一个字段为MN-MN到M字段剪切单元-b以字节为单位-c以字符为单位-f以字段为单位(使用定界符)eg:cut-c1-5file//打印前5个字符cut-c-2file//打印前2个characters8,pastesplicingtextbycolumn将两个文本按列拼接在一起;catfile112catfile2colinbookpastefile1file21colin2book默认分隔符是制表符,可以使用-d指定分隔符粘贴file1file2-d","1,colin2,book9,wc行数统计工具wc-lfile//统计数量lineswc-wfile//统计字数wc-cfile//统计字符数10、sed文本替换工具先replaceseg's/text/replace_text/'file//替换每行第一个匹配的文本和globalreplaceseg's/text/replace_text/g'file默认替换后,输出替换后的内容,如果需要直接替换原文件,使用-i:seg-i's/text/repalce_text/g'file去除空行:sed'/^$/d'文件变量转换匹配的字符串由标记&.echothisisenexample|引用seg's/w+/[&]/g'$>[this][is][en][example]子串匹配tag首先匹配括号内容用tag来引用sed的/hello([0-9])//'双引号评估sed通常用单引号引起来;也可以使用双引号。使用双引号后,双引号会对表达式求值:sed's/$var/HLLOE/'使用双引号时,我们可以在sed模式和替换字符串中指定变量;eg:p=pattenr=replacedecho"lineconapatten"|sed"s/$p/$r/g"$>lineconareplaced其他示例字符串插入字符:替换每行文本(PEKSHA)转换为PEK/SHASed's/^.{3}/&//g'file11、awk数据流处理工具awk脚本结构awk'BEGIN{statements}statements2END{statements}'工作方法1.执行begin中的语句块;2、从文件或stdin中读取一行,然后执行statements2,重复这个过程,直到读取完所有文件;3.执行结束语句块;print打印当前行当使用不带参数的print时,将打印当前行;echo-e"line1ine2"|awk'BEGIN{print"start"}{print}END{print"End"}'print以逗号分隔时,参数以空格分隔;echo|awk'{var1="v1";var2="V2";var3="v3";printvar1,var2,var3;}'$>v1V2v3使用-拼接字符(""为拼接字符);echo|awk'{var1="v1";var2="V2";var3="v3";printvar1"-"var2"-"var3;}'$>v1-V2-v3特殊变量:NRNF$0$1$2NR:表示记录数,执行时对应当前行号;NF:表示字段数,执行时始终对应当前行的字段数;$0:该变量包含执行时当前行的文本内容;$1:第一个字段的文本内容;$2:第二个字段内容的文本;echo-e"line1f2f3line2line3"|awk'{printNR":"$0"-"$1"-"$2}'打印每行的第二个和第三个字段:awk'{print$2,$3}'filestatistics文件中的行数:awk'END{printNR}'文件累加每一行的第一个字段:echo-e"1234"|awk'BEGIN{num=0;print"begin";}{sum+=$1;}END{print"==";printsum}'传递外部变量var=1000echo|awk'{printvara}'vara=$var#Inputcomesfromstdinawk'{printvara}'vara=$varfile#Inputcomesfromafileandhandlesawkwithstyle过滤行awk'NR<5'#行号小于5awk'NR==1,NR==4{print}'file#行号等于1和4打印出来awk'/linux/'#包含linux文本的行(可以用??正则表达式指定,超级强大)awk'!/linux/'#为不包含linux文本的行设置分隔符使用-F设置分隔符(默认是aspace)awk-F:'{print$NF}'/etc/passwd读取命令输出使用getline将外部shell命令的输出读入变量cmdout;echo|awk'{"greproot/etc/passwd"|getlinecmdout;printcmdout}'在awk中使用循环for(i=0;i<10;i++){print$i;}for(iinarray){printarray[i];}例如:以相反的顺序打印行:(tac命令的实现)seq9|awk'{lifo[NR]=$0;lno=NR}END{for(;lno>-1;lno--){printlifo[lno];}}'awk实现head和tail命令head:awk'NR<=10{print}'filenametail:awk'{buffer[NR%10]=$0;}END{for(i=0;i<11;i++){printbuffer[i%10]}}'filename打印指定列awk:ls-lrt|awk'{print$6}'cut方法实现ls-lrt|cut-f6打印指定文本区域确定行numberseq100|awk'NR==4,NR==6{print}'判断文字打印在Textbetweenstart_patternandend_pattern;awk'/start_pattern/,/end_pattern/'filenameeg:seq100|awk'/13/,/15/'cat/etc/passwd|awk'/mai.*mail/,/news.*news/'awk常用内置函数index(string,search_string):返回字符串中search_string出现的位置sub(regex,replacement_str,string):替换正则匹配到的第一个内容带有replacement_str的表达式;match(regex,string):检查正则表达式是否可以匹配字符串;length(string):返回字符串的长度echo|awk'{"greproot/etc/passwd"|getlinecmdout;printlength(cmdout)}'printf类似于c语言中的printf,格式化输出eg:seq10|awk'{printf"->%4s",$1}'12、遍历文件中的行、词、字符(1)遍历文件中的每一行while循环方法whilereadline;doecho$line;done
