从零开始学shell之正则表达式

正则表达式

定义:

正则表达式是你所定义的模式模版,Linux工具可以用它来过滤文本。很多Linux工具能够在处理数据的时候使用正则表达式对数据进行模式匹配。如果数据匹配,就会接受并进一步处理;如果数据不匹配,就会被过滤掉
例子:用正则表达式列出.sh结尾的文件
ls -al *.sh

类型

正则表达式的问题在于不只有一种类型的正则表达式。Linux中不同应用程序可能会使用不同类型的正则表达式。其中包括编程程序(Java,Perl,Python等)、Linux实用工具(grep,sed,awk等)以及主流应用(MySQL)。
正则表达式是通过正则表达式引擎实现的。主流的正则表达式引擎只有两种:

  1. POSIX基础正则表达式引擎
  2. POSIX扩展正则表达式引擎 大多数至少符合基础正则表达式引擎。

语法

匹配字符

语法含义.匹配任意一个字符[abc]匹配一个字符,这个字符是a,b,c中的一个[a-zA-Z]匹配一个字符,这个字符是a到z或者A到Z这些字符中的一个[^123]匹配一个字符,这个字符是除了1,2,3以外的所有字符

匹配次数

\{m,n\} : 匹配前面出现的字符至少m次,至多n次
\?: 匹配前面出现的字符0次或者1次。
+: 匹配前面的字符1次或多次,但至少出现1次,模式才会匹配。
*: 匹配前面出现的字符任意次。所以 .*表示任意字符任意次,即什么内容都匹配。

ps:
+和*是贪心模式,只要符合条件就会一直匹配下去。
比如:hello+ 会匹配hello或者helloooooo....等无数个o
hello* 会匹配hell和hellooooo....等无数个o

其余的是非贪心模式,贪心模式后加上非贪心模式的限定会变为非贪心模式,比如:

<h1>hello<h1> 正则表达式是<.+> 会匹配到<h1>hello<h1>。但是如果是<.+?>,匹配的结果就是<h1>。但是如果使用grep命令匹配,在匹配h1后打印一行,然后会继续走接下来的匹配,所以会匹配到后面的/h1,在下面一行打印出来,如下所示:
<h1>
</h1>

位置锚定

^: 锚定行首,这个要写在表达式头部
$: 锚定行尾,这个要写在表达式尾部
\b或\<: 锚定单词的词首。如\blike不会匹配alike,但是会匹配liker。
\b或\>:锚定单词的词尾。如\blike\b不会匹配alike和liker,只会匹配like。
\B :与\b作用相反。也就是不会匹配词首或词尾。

管道符号

管道符号允许你在检查数据流时,用逻辑or方式指定正则表达式引擎要用的两个或多个模式。如果任何一个模式匹配了数据流文本,文本就通过测试。

expr1|expr2...

eg:[ch]at|dog 会匹配cat,hat或dog

表达式分组

被分为一组的表达式会被视为一个标准字符。
eg:Sat(urday)?
urday视为一个字符,(urday)?匹配一次或零次。所以这个正则表达式会匹配Sat或Saturday。

正则表达式实战

目录文件统计

mypath=$(echo $PATH | sed 's/:/ /g')
for directory in $mypath
do
echo $directory
done

将path变量中的分号替换成空格,然后久可以循环打印了
ps:for 默认是以空格分隔的。

打印当前目录下的文件和目录

for FILE in $(ls); do echo $FILE; done

ps:

  1. $(command) 运行命令作为结果
  2. ls -al  | egrep " .+" | wc -l 统计所有.开头的文件或者文件名。

解析邮件地址

^([a-zA-Z0-9_\-\.\+]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5})$

ps:

  1. 用^锚定行首
  2. [a-zA-Z0-9_-.+] 表明合法的字符集是26个大小写英文字母,数字,-,.,+。至少出现一次。
  3. 匹配@符号
  4. $匹配最后的域名结尾{2,5},两到五个字符

总结

正则表达式还有很多需要学习,继续努力