本文将介绍Linux下使用Shell处理文本时最常用的工具:find、grep、xargs、sort、uniq、tr、cut、paste、wc、sed、awk;提供的例子和参数是最常用和最实用的;我用shell脚本的原则是把命令写在一行中,尽量不要超过2行;如果你有更复杂的任务需求,可以考虑python;findfilesearch查找txt和pdf文件find.\(-name"*.txt"-o-name"*.pdf"\)-print常规方式查找.txt和pdffind.-regex".*\(\.txt|\.pdf\)$"-iregex:忽略不区分大小写的正则否定参数,查找所有非txt文本find.!-name"*.txt"-print指定搜索深度,打印出其中的文件当前目录(深度为1)find.-maxdepth1-typef自定义搜索类型搜索:find.-typed-print//只列出所有目录-typeffile/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-name"*.swp"-delete执行动作(强大的exec)find.-typef-userroot-execchownweber{}\;//将当前的归属目录改为weber注意:{}是一个特殊的字符串,对于每一个匹配的文件,{}都会被替换为对应的文件名;例如:将找到文件将所有文件复制到另一个目录:find.-typef-mtime+10-name"*.txt"-execcp{}OLD\;合并多条命令提示:如果后面需要执行多条命令,可以将多条命令写成一个脚本,然后在调用-exec时执行该脚本;-exec./commands.sh{}\;-print的分隔符默认使用'\n'作为文件分隔符;-print0使用'\0'作为文件的分隔符,这样就可以搜索包含空格的文件;greptextsearchgrepmatch_pattenfile//默认获取匹配行常用参数-o只输出匹配的文本行VS-v只输出不匹配的文本行-c统计文件包含文本的次数grep-c"text"文件名-n打印匹配行号-i搜索时忽略大小写-l只打印文件名递归搜索多级目录中的文本(程序员最喜欢的代码搜索):grep"class".-R-n匹配多种模式grep-e"class"-e"vitural"filegrep输出以\0结尾的文件名:(-z)grep"test"file*-lZ|xargs-0rmxargs命令行参数转换xargs可以将输入数据转换为特定命令的命令行参数;这样,它可以与许多命令结合使用。比如grep,比如find;将多行输出转换为单行输出catfile.txt|xargs\n是多行文本之间的分隔符将单行转换为多行输出catsingle.txt|xargs-n3-n:指定每行显示的字段数xargs参数说明-d定义分隔符(默认为空格,多行分隔符为\n)-n指定输出为多行-I{}指定替换字符串,这个字符串在xargs展开时,当要执行的命令需要多个参数时会被替换eg:catfile.txt|xargs-I{}./command.sh-p{}-1-0:指定\0为输入分隔符eg:统计程序行数findsource_dir/-typef-name"*.cpp"-print0|xargs-0wc-lsort排序字段说明:-n按数字排序VS-d按字典顺序排序-r逆序排序-kN指定按第N列排序eg:sort-nrk1data.txtsort-bddata//忽略空格等前导空白字符uniq消除重复行消除重复行sortunsort.txt|uniqCount每行在文件中出现的次数sortunsort.txt|uniq-c找出重复行ortunsort.txt|uniq-d可以指定每一行需要比较的重复内容:-s开始位置-w比较字符数,用tr转换一般用法echo12345|tr'0-9''9876543210'//加解密转换,替换对应字符cattext|tr'\t'''//tab转空格tr删除字符catfile|tr-d'0-9'//deleteallnumbers-ccomplementSetcatfile|tr-c'0-9'//获取文件中的所有数字catfile|tr-d-c'0-9\n'//删除非数字数据tr压缩字符tr-s压缩文本字符的重复;最常用于压缩冗余空格catfile|tr-s''字符类tr中提供各种字符类:alnum:字母和数字alpha:字母digit:数字space:空白字符lower:小写upper:大写cntrl:control(非-printable)characters打印:可打印字符用法:tr[:class:][:class:]eg:tr'[:lower:]''[:upper:]'cut按列拆分文本并截取文件的第二列和第四列:cut-f2,4filename删除文件除第三列以外的所有列:cut-f3--complementfilename-d指定分隔符:cat-f2-d";"文件名剪切范围为N-第N个字段到末尾-M第一个字段为MN-M从N到M个字段的剪切单位-b以字节为单位-c以字节为单位字符的单位-f为字段的单位(使用分隔符)eg:cut-c1-5file//打印前5个字符cut-c-2file//打印前2个字符paste按列拼接文本两者文本按列拼接在一起;catfile112catfile2colinbookpastefile1file21colin2book默认分隔符是制表符,可以用-d指定分隔符pastefile1file2-d","1,colin2,bookwc统计行数和字符数的工具wc-lfile//统计wc的行数-wfile//统计字数wc-cfile//统计字符数全局替换seg's/text/replace_text/g'file默认替换后,输出替换后的内容。如果需要直接替换原文件,使用-i:seg-i's/text/replace_text/g'file去掉空行:sed'/^$/d'filevariableconvertsmatchedstringstoreferencesby&.echothisisenexample|seg's/\w+/[&]/g'$>[this][is][en][example]子串匹配标记第一个匹配的括号内容使用标记\1来引用sed's/hello\([0-9]\)/\1/'双引号求值ed通常用单引号引用;也可以使用双引号,使用双引号后,双引号对表达式求值:sed's/$var/HLLOE/'使用双引号时,我们可以在sed模式和替换字符串中指定变量;例如:p=pattenr=replacedecho"lineconapatten"|sed"s/$p/$r/g"$>lineconareplacedotherexamplestringinsertioncharacter:Converteachlineoftext(PEKSHA)toPEK/SHASed's/^.\{3\}/&\/字符串插入字符:/g'fileawk数据流处理工具awk脚本结构awk'BEGIN{statements}statements2END{statements}'工作方式1.执行begin中的语句块;2.从文件或stdin中读取一行,然后执行statements2,重复这个过程,直到所有的文件都读完;3.执行end语句块;print打印当前行当使用不带参数的print时,将打印当前行;echo-e"line1\nline2"|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:表示记录数,c执行时对应当前行号;NF:表示字段数,在执行过程中总是对应当前行的字段数;$0:该变量包含执行时当前行的文本内容;$1:第一个字段的文本内容;$2:第二个字段的文本内容;echo-e"line1f2f3\nline2\nline3"|awk'{printNR":"$0"-"$1"-"$2}'打印第二个和第三个字段:awk'{print$2,$3}'file统计文件的行数:awk'END{printNR}'file累加每一行的第一个字段:echo-e"1\n2\n3\n4\n"|awk'BEGIN{num=0;print"begin";}{sum+=$1;}END{print"==";printsum}'传递外部变量var=1000echo|awk'{printvara}'vara=$var#输入来自stdinawk'{printvara}'vara=$varfile#输入来自文件,使用style过滤awk处理的行awk'NR<5'#行号小于5awk'NR==1,NR==4{print}'file#打印行号等于1的行和4awk'/linux/'#包含linux文本的行(可以用??正则表达式指定,超级强大)awk'!/linux/'#不包含linux文本的行设置分隔符使用-F设置分隔符(默认为空格)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}'剪切模式执行ls-lrt|cut-f6打印指定文本区域确定行号seq100|awk'NR==4,NR==6{print}'确定文本打印start_pattern和end_pattern之间的文本;awk'/start_pattern/,/end_pattern/'filenameeg:seq100|awk'/13/,/15/'cat/etc/passwd|awk'/mai.*mail/,/news.*news/'awk常用内置-infunctionindex(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\n",$1}'迭代文件中的行、词和字符1.迭代文件中的每一行while循环方法whilereadline;doecho$line;done
