通配符和正则表达式
第一次觉得Linux的强大是因为接触到了grep这个命令,然后写的大多数脚本都用到了管道+grep,后来又接触到了awk和sed,才知道强大的不是命令而是正则表达式。 后来发现当我要查找某个文件时用到了find,然后从百度上找到了一些文件名匹配的方式,我以为我依然使用的是正则,直到后来看了鸟叔才知道这个使用的是通配符,而且他也一再强调一定要把正则和通配符分开,所以今天写一篇关于正则表达式和通配符的文章。 个人理解:通配符是对文件操作;正则表达式是对字符串的匹配--》在Linux中
1.)通配符--》顾名思义,满足条件的通通匹配 Linux中包含了如下通配符 1.1)*--》匹配任一多个字符(包含0个) 举例如下: <如果想查找home目录下的一个文件,只记得这个文件名中包含file>执行如下命令即可 find /home -name*file*则可以匹配 file afile aafile fileb filebb afileb afilebb ... <如果想删除/home/test目录下的所有文件>执行如下命令即可 rm -f /home/test/*如果子目录也要删除则执行 rm -rf /home/test/* 建议使用*来批量删除文件前最后按两次tab,这样控制台会打印出所有你想删的文件,确保好了再删除,毕竟删除后想找回来还是很麻烦的。
1.2)?--》匹配任意的一个字符 /tmp/目录下有a b c aaab ac bb cc aaa aab bbb ccc文件, <如果想删除单个字符的文件> rm -f ? <如果想删除aa ab ac这些文件> rm -f a? //思考,a会被删除吗???
1.3)[] --》匹配括号内的字符 /tmp/目录下有a b c aaab ac bb cc aaa aababb acb adbccc文件, <如果想删除aab abb acb这两个文件> rm -f a[abc]b <如果想删除aab abb acb adb> rm -f a[a-d]b or rm -f a?b //思考 rm -f a*b可以吗??? <如果想把/tmp/aaa文件中小写字母全部转换为大写> cat /tmp/aaa| tr [a-z] [A-Z]
1.4) [!] --》不匹配括号内的字符 /tmp/目录下有a b c aaab ac bb cc aaa aababb acb adbccc文件, <如果想得到不是以a开头的所有文件(b c bb cc ccc)> ls [!a]*
1.5) 举个错误的例子 /tmp目录有file1 file2 file3 file4tmpfile文件 #cat /tmp/tmpfile //控制台中输入命令,下面的是结果 aba abb abc # cat /tmp/tmpfile | grep ab[a-z] //输出和想的相同 aba abb abc // 如果此时我执行如下命令 # touch abd; cat /tmp/tmpfile | grep ab[a-z] //输出确为空,想想为什么???后面会揭晓答案。 // 然后执行如下命令 # echo ab? >> /tmp/tmpfile; cat /tmp/tmpfile | grep ab[a-z] abd //结果是否和你预期的一样,思考一下,你就会知道之前为什么输出空了。 // 因为执行grep ab[a-z]的时候,Linux首先会匹配通配符,所以对于为空的指令是因为Linux中执行的命令是 #cat /tmp/tmpfile | grep abd //所以输出为空,通过echo ab? >> /tmp/tmpfile后查看文件内容可以看到文件尾部插入了adb,所以正确的翻译是echo abd >> /tmp/tmpfile *** 修改方式:cat /tmp/tmpfile | grep ab[a-z];则通配符匹配的过滤后执行 cat /tmp/tempfile | grep ab[a-z],然后正则匹配的时候得到想要的结果 // 而开始不为空是因为Linux匹配通配符的时候没有匹配到所以执行了 #cat /tmp/tmpfile | grep[a-z];然后作为正则表达式匹配的时候找到了aba abb abc. *** 修改方式: cat /tmp/tmpfile | grep "ab[a-z]",直接当做正则来匹配 //bash对于通配符相关的字符进行了特别的处理,所以包含这些参数的命令需要非常小心,尽量使用来转义。
2)正则表达式 --》顾名思义,按正经的规则表达式来匹配 正则表达式是字符和元字符的集合,其中的一些概念如下
2,1)字符集 可以理解为普通的字符,空格也算
2.2)锚 可以理解为固定的位置,很形象。^, $,&;, &;. 其中^表示行首,$表示行尾,&;表示单词开始的字符,&;表示单词结尾的字符 <如果想匹配以a开始以b结束的行> grep "^a" | grep "b$"或者 grep "^a.*b$" //这里的|不是或的意思,是管道 <如果想匹配包含以f开头k结尾的单词的行> grep "&;f" | grep "b&;"或者grep "&;f.*k&;"
2.3)元字符 2.3.1) * --》匹配前一个字符零次或任意多次(注意,必须和前一个字符比较。注意和通配符的区别) grep "a*" /tmp/tmpfile--》输出tmpfile的所有内容(注意是匹配a零次或多次,因为所以行都可以匹配"",即0次a) grep "aa*" /tmp/tmpfile --》输出tmpfile中包含a或者aa或者aaa或者aaaa...的行(至少包含一个a,其实可以匹配aa则一定可以被a匹配) grep "aaa*" /tmp/tmpfile--》输出tmpfile中包含aa或者aaa...的行
2.3.2)+--》匹配前一个字符任意多次(不包含0次,与*的唯一差别) grep "a+" /tmp/tmpfile--》输出结果等同 grep aa* /tmp/tmpfile grep "aa+" /tmpfile --》输出结果等同 grep aaa* /tmp/tmpfile
2.3.3).--》匹配任意字符一次,但不能匹配换行符 grep "a. /tmp/tempfile --》与grep aa* /tmp/tmpfile的唯一区别是不能匹配仅有一个a,且这个a在结尾(即a的下一个字符是换行)
2.3.4) []匹配属于集合中的任意一个字符 grep“[a-z]” /tmp/tempfile --》匹配文件中包含字母的行
2.3.5)[^]匹配不属于集合中的任意字符 grep“[^a-z]” /tmp/tmpfile--》匹配不包含字母的行
2.3.6){m}匹配前一个字母m次(m为指定数字) grep“a{3}”/tmp/tmpfile --》匹配包含aaa的行
2.3.7){m,}匹配前一个字符至少m次
2.3.8){m,n}匹配前一个字符最少m次,最多n次
正则表达式很复杂,需要反复的锻炼才行,建议与VIM的学习结合起来。
// 简单的例子 1. /tmp下有aaa bbc dde 三个文件, 想grep出aaa bbc文件 # ls | grep -v dde // 如果/tmp下还有其他文件就失效了, 很明显这种想法是不可取 # ls | grep "aaa|bbc" // grep的或实现 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |