通配符和正则表达式

第一次觉得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 aa ab ac bb cc aaa aab bbb ccc文件,

<如果想删除单个字符的文件>

rm -f ?

<如果想删除aa ab ac这些文件>

rm -f a?            // 思考,a会被删除吗???


1.3) []     --》 匹配括号内的字符

/tmp/目录下有a b c aa ab ac bb cc aaa aab abb acb adb ccc文件,

<如果想删除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 aa ab ac bb cc aaa aab abb acb adb ccc文件,

<如果想得到不是以a开头的所有文件(b c bb cc ccc)>

ls [!a]*


1.5) 举个错误的例子

/tmp目录有file1 file2 file3 file4 tmpfile文件

# 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的或实现









  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值