Linux Shell 脚本编程(5)—文本过滤(正则表达式)
文本过滤
- 正则表达式 –Linux Shell 脚本编程(5)—文本过滤(正则表达式)
- grep 命令 –Linux Shell 脚本编程(6)—文本过滤(grep命令)
- find命令 –Linux Shell 脚本编程(7)—文本过滤(find命令)
- awk
- sed
- 合并与分割(sort、uniq、join、cut、paste、split)
正则表达式
- 概念:一种用来描述文本模式的特殊语法
由普通字符(例如:字符a到z),以及特殊字符(元字符,如/ * ?等)组成匹配的字符串 - 文本过滤工具在某种模式之下,都支持正则表达式。
- 注意!!!正则表达式,是以字符进行匹配的!!!!
1. 基本元字符集及其含义
元字符 | 含义 |
---|---|
^ | 只匹配行首 |
$ | 只匹配行尾 |
* | 单字符后紧跟*,匹配0个或多个此单字符 |
[ ] | 匹配[ ]内字符。可以是一个单字符,也可以是字符序列。可以使用.表示[ ]内字符序列范围,如用[1-5]代替[12345] |
\ | 用来屏蔽一个元字符的特殊含义。因为有时在shell中一些元字符有特殊含义。\可以使其失去应有意义 |
. | 匹配任意单字符 |
pattern{n} | 用来匹配前面pattern出现次数。n为次数 |
pattern{n, }m | 含义同上,但次数至少为n |
pattern{n,m} | 含义同上,但pattern出现次数在n和m之间 |
#---grep命令使用---
jianliu@ubuntu:~/aa$ ls -l *.c
lrwxrwxrwx 1 jianliu jianliu 3 Oct 7 20:07 2.c -> 1.c
-rw-rw-r-- 1 jianliu jianliu 79 Oct 3 05:05 a1.c
-rw-rw-r-- 1 jianliu jianliu 79 Oct 3 05:17 b1.c
lrwxrwxrwx 1 jianliu jianliu 4 Oct 7 20:07 b3.c -> b1.c
lrwxrwxrwx 1 jianliu jianliu 4 Oct 7 20:07 b4.c -> b1.c
-rw-rw-r-- 1 jianliu jianliu 94 Oct 4 04:20 hello.c
jianliu@ubuntu:~/aa$ ls -l ?.c
lrwxrwxrwx 1 jianliu jianliu 3 Oct 7 20:07 2.c -> 1.c
#匹配权限位 \-:普通文件; r:所有者具有读权限。
#\-:‘-’特殊字符,进行转义!!!!
jianliu@ubuntu:~/aa$ ls -l | grep "\-r........"
-rw-rw-r-- 1 jianliu jianliu 79 Oct 3 05:05 a1.c
-rwxrwxr-x 1 jianliu jianliu 8501 Oct 6 19:26 app2
-rw-rw-r-- 1 jianliu jianliu 79 Oct 3 05:17 b1.c
-rw-rw-r-- 1 jianliu jianliu 0 Oct 7 23:16 efile
-rwxrwxr-x 1 jianliu jianliu 0 Oct 10 05:26 exe.app
-rw-rw-r-- 1 jianliu jianliu 94 Oct 4 04:20 hello.c
-rwxrwxr-x 1 jianliu jianliu 58 Oct 10 05:51 names.txt
-rwxrwxr-x 1 jianliu jianliu 0 Oct 10 05:49 names.txt~
-rw------- 1 jianliu jianliu 225 Oct 10 05:33 nohup.out
-r--r--r-- 1 jianliu jianliu 0 Oct 7 20:25 rd_file
-rwxr-xr-x 1 jianliu jianliu 109 Oct 6 19:15 shell01.sh
-rwxr-xr-x 1 jianliu jianliu 109 Oct 6 19:15 shell02.sh
-rwxrwxr-x 1 jianliu jianliu 382 Oct 10 06:49 test.sh
-rwxrwxr-x 1 jianliu jianliu 337 Oct 10 06:48 test.sh~
-rw-rw-r-- 1 jianliu jianliu 4827 Oct 7 23:21 test.txt
jianliu@ubuntu:~/aa$ ls -l | grep 'shell0.'
-rwxr-xr-x 1 jianliu jianliu 109 Oct 6 19:15 shell01.sh
-rwxr-xr-x 1 jianliu jianliu 109 Oct 6 19:15 shell02.sh
2. 使用句点匹配单字符
- 句点“.”可以匹配任意单字符。
例如,如果要匹配一个字符串,以 beg开头,中间夹一个任意字符,那么可以表示为b e g . n, “.”可以匹配字符串头,也可以是中间任意字符。
在ls -l命令中,可以匹配一定权限:
#在ls-l命令中,可以匹配一定权限:
...x..x..x (pattern)
此格式匹配用户本身,用户组及其他组成员的执行权限。
drwxrwxrw- 未匹配
-rw-rw-rw- 未匹配
-rwxrwxr-x 匹配
-rwx-r-xr-x 匹配
假定正在过滤一个文本文件,对于一个有10个字符的脚本集,要求前4个字符之后为xc,匹配操作如下
....xc....
1234xc9870 匹配
2432xx0977 不匹配
0023xa3456 不匹配
9932xc3421 匹配
#注意! “.”允许匹配ASCII集中任意字符、或者字母、或者数字。
3. 行首以^匹配字符串或字符序列
- 只允许在一行的开始匹配字符或单词。例如,使用 ls -l命令,匹配目录。之所以可以样做是因为ls -l命令结果每行第一个字符是d,即代表一个目录。
^d
drwxrwxrw- 匹配
-rwxrw--wx 不匹配
drw-r-xr-- 匹配
^001
1234cx2345 不匹配
2353xx9011 不匹配
0011xa8345 匹配
jianliu@ubuntu:~/aa$ ls -l | grep ^d
drwxrwxr-x 3 jianliu jianliu 4096 Oct 3 06:44 bb
jianliu@ubuntu:~/aa$ ls -l | grep ^.rw.rw.r..
lrwxrwxrwx 1 jianliu jianliu 3 Oct 7 20:07 2.c -> 1.c
-rw-rw-r-- 1 jianliu jianliu 79 Oct 3 05:05 a1.c
-rwxrwxr-x 1 jianliu jianliu 8501 Oct 6 19:26 app2
-rw-rw-r-- 1 jianliu jianliu 79 Oct 3 05:17 b1.c
lrwxrwxrwx 1 jianliu jianliu 4 Oct 7 20:07 b3.c -> b1.c
lrwxrwxrwx 1 jianliu jianliu 4 Oct 7 20:07 b4.c -> b1.c
drwxrwxr-x 3 jianliu jianliu 4096 Oct 3 06:44 bb
-rw-rw-r-- 1 jianliu jianliu 0 Oct 7 23:16 efile
-rwxrwxr-x 1 jianliu jianliu 0 Oct 10 05:26 exe.app
-rw-rw-r-- 1 jianliu jianliu 94 Oct 4 04:20 hello.c
-rwxrwxr-x 1 jianliu jianliu 58 Oct 10 05:51 names.txt
-rwxrwxr-x 1 jianliu jianliu 0 Oct 10 05:49 names.txt~
-rwxrwxr-x 1 jianliu jianliu 382 Oct 10 06:49 test.sh
-rwxrwxr-x 1 jianliu jianliu 337 Oct 10 06:48 test.sh~
-rw-rw-r-- 1 jianliu jianliu 4827 Oct 7 23:21 test.txt
#将各种模式结合使用
^...4cx....
#结果为:
1234cx2345 匹配
2354cc9011 不匹配
4564cx8345 匹配
#查找shell01.sh中的注释
jianliu@ubuntu:~/aa$ grep ^# shell01.sh
#!/bin/bash
#echo $4
#echo $5
4. 行尾以$匹配字符串或字符
- 可以说
$
与^
正相反,它在行尾匹配字符串或字符,$
符号放在匹配单词后。假定要匹配以词trouble结尾的所有行,操作为:trouble$
jianliu@ubuntu:~/aa$ ls -l | grep c$
lrwxrwxrwx 1 jianliu jianliu 3 Oct 7 20:07 2.c -> 1.c
-rw-rw-r-- 1 jianliu jianliu 79 Oct 3 05:05 a1.c
-rw-rw-r-- 1 jianliu jianliu 79 Oct 3 05:17 b1.c
lrwxrwxrwx 1 jianliu jianliu 4 Oct 7 20:07 b3.c -> b1.c
lrwxrwxrwx 1 jianliu jianliu 4 Oct 7 20:07 b4.c -> b1.c
-rw-rw-r-- 1 jianliu jianliu 94 Oct 4 04:20 hello.c
^$ 匹配空行
^.$ 匹配包含一个字符的行
5. 用*$匹配单字符串或或其重复序列
匹配字符u一次或多次
comter
computer
compuuter
compuuuuter
6. 使用\屏蔽一个特殊字符的含义
- 忽视该特殊字符的含义,仅认为其是一个普通字符。
#特殊字符如下:
$ . ' " * [ ] ^ | 0 \ + ?
假定要匹配包含字符"."的各行,而"."代表匹配任意单字符的特殊字符,因此需要屏蔽其含义。操作如下:
\.
上述模式不认为反斜杠后面的字符是特殊字符,而是一个普通字符,即句点。
假定要匹配包含^的各行,将反斜杠放在它前面就可以屏蔽其特殊含义。如下: \^
如果要在正则表达式中匹配以".pas"结尾的所有文件,可做如下操作:
\*\.pas
即可屏蔽字符*的特殊含义。
7. 使用[ ] 匹配一个范围或集合
- [A-Z] : A的左侧和Z的右侧不能有空格!!, -的左右均不能有空格!!!
- [A-Za-z]: 用于匹配所有字母,其中Z和a中间不能有空格!!!
#1 假定要匹配任意一个数字,可以使用:
[0123456789]
jianliu@ubuntu:~/aa$ ls -l | grep shell[012][012]\.
-rwxr-xr-x 1 jianliu jianliu 109 Oct 6 19:15 shell01.sh
-rwxr-xr-x 1 jianliu jianliu 109 Oct 6 19:15 shell02.sh
#2 使用"-"简化匹配任意一个数字的操作
[0-9] #匹配数字
jianliu@ubuntu:~/aa$ touch shell03.sh
jianliu@ubuntu:~/aa$ touch shell10.sh
jianliu@ubuntu:~/aa$ touch shell11.sh
jianliu@ubuntu:~/aa$ ls -l | grep shell[0-9][0-9]\.
-rwxr-xr-x 1 jianliu jianliu 109 Oct 6 19:15 shell01.sh
-rwxr-xr-x 1 jianliu jianliu 109 Oct 6 19:15 shell02.sh
-rw-rw-r-- 1 jianliu jianliu 0 Oct 11 07:59 shell03.sh
-rw-rw-r-- 1 jianliu jianliu 0 Oct 11 07:59 shell10.sh
-rw-rw-r-- 1 jianliu jianliu 0 Oct 11 07:59 shell11.sh
#3
[a-z] 任意小写字符 #正确写法
[ a-z ] #错误!! [a - z] #错误
#4-------------------------------------------------------------
[A-Za-z] 从 A-Z、a-z的字母范围
[A-Z a-z] #错误!!
#5-----------------------------------------------------------
[A-Za-z0-9] 匹配任意字母或数字
jianliu@ubuntu:~/aa$ cat test0.txt
a
D
e
c
f
3
1
5
7
jianliu@ubuntu:~/aa$ cat test0.txt | grep [A-Ca-c0-3]
a
c
3
1
#6------------------------------------------------
#在字符序列结合使用中,可以用 [ ]指出字符范围。假定要匹配一单词,以 s开头,中间有任意字母,以t结尾,那么操作如下:
s[a-zA-Z]t
jianliu@ubuntu:~/aa$ cat test0.txt
st
sat
sbt
s@t
s2t
saat
sbbt
sabt
saaat
sbbbt
sabct
jianliu@ubuntu:~/aa$ cat test0.txt | grep s[a-zA-Z]t
sat
sbt
jianliu@ubuntu:~/aa$ cat test0.txt | grep s[a-zA-Z]*t
st
sat
saat
sabt
saaat
sabct
#7--------------------------------------------------
#匹配所有包含system后跟句点的所有单词,这里S可大写或小写。
jianliu@ubuntu:~/aa$ cat test0.txt
system.h
system
System.h
asytem.h
jianliu@ubuntu:~/aa$ cat test0.txt | grep [S,s]ystem\.
system.h
System.h
8. ^位于[ ]中,即[^符号集]匹配除符号集以外的其他单字符
jianliu@ubuntu:~/aa$ cat test0.txt
st
sat
sbt
s@t
s%t
s*&t
s2t
s3t
saat
sbbt
s22t
s33t
s@@t
s%%t
sabt
saaat
sbbbt
sabct
jianliu@ubuntu:~/aa$ cat test0.txt | grep s[^a-zA-Z0-9]*t
st
s@t
s%t
s*&t
s@@t
s%%t
- 使用\{ \}匹配模式设置模式出现的次数
- pattern\{n\} 匹配模式出现n次。
- pattern\{n,\} 匹配模式出现最少n次。
- pattern\{n,m\} 匹配模式出现n到m次之间,n , m为0 - 2 5 5中任意整数。
jianliu@ubuntu:~/aa$ cat test0.txt
st
sat
saat
saaat
sbt
sbbt
sbbbt
s2t
s22t
s222t
s@@t
s%%t
sabt
sabct
jianliu@ubuntu:~/aa$ cat test0.txt | grep 'sa\{2\}t'
saat
jianliu@ubuntu:~/aa$ cat test0.txt | grep 'sa\{2,\}t'
saat
saaat
jianliu@ubuntu:~/aa$ cat test0.txt | grep 'sa\{1,3\}t'
sat
saat
saaat
jianliu@ubuntu:~/aa$ cat test0.txt | grep 's[a-z]\{1,3\}t'
sat
saat
saaat
sbt
sbbt
sbbbt
sabt
sabct
jianliu@ubuntu:~/aa$ cat test0.txt | grep 's[a-z0-9]\{1,3\}t'
sat
saat
saaat
sbt
sbbt
sbbbt
s2t
s22t
s222t
sabt
sabct
#注意!!!
cat test0.txt | grep sa\{2\}t //写法错误!!,不能省去' '
9. 匹配子串( )
jianliu@ubuntu:~$ echo -e "mabc\n mc\n mac" | grep -E 'm(ab)?c'
mabc
mc
jianliu@ubuntu:~$ echo -e "mabc\n mc\n mac" | grep 'm\(ab\)\?c'
mabc
mc
##注意两种写法的区别,详细见下一篇博客【grep】
10. 匹配给定文本中所有的单词
```C++
( ?[a-zA-Z]+ ?)
#“?”用于匹配单词前后可能出现的空格。 [a-zA-Z]+代表一个或多个字母(a~z和A~Z)。
//?前有一个空格!!!
```
11. 匹配一个IP地址
192.168.12.2
127.123.1.5
192.168.1.
....
192.168.1
jianliu@ubuntu:~/aa$ cat test0.txt | grep '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}'
192.168.12.2
127.123.1.5
jianliu@ubuntu:~/aa$ cat test0.txt | grep '[[:digit:]]\{1,3\}\.[[:digit:]]\{1,3\}\.[[:digit:]]\{1,3\}\.[[:digit:]]\{1,3\}'
192.168.12.2
127.123.1.5
12. 匹配邮箱
jianliu@ubuntu:~/aa$ cat test0.txt
jianliu0627@qq.com
dfhao@163.com
1122333@foxmail.com
_hha23@qq.com
+hhaa12@qq.com
jianliu98qqcom
joann@163com
__123qq@163com
jianliu@ubuntu:~/aa$ cat test0.txt | grep '[a-zA-Z0-9_]\{1,\}@[a-z0-9]\{1,3\}\.[a-z]\{1,\}'
jianliu0627@qq.com
dfhao@163.com
_hha23@qql.com