正则表达式是一种字串表达的方式,可用以指定具有某特征的所有字串。在 linux 里,正则表达式被应用得非常广泛,但是不同的工具中使用方法略有不同。本文主要来看下面几种容易混淆的情况。
一、Linux中正则表达式的基本知识
1、了解组成基本正则表达式的元素。
字符 | 意义和用法 |
---|---|
点号(.) | 任意字符 |
斜线(\) | 表示转意字符,比如点号,如果真的需要匹配点号本身,则需要用 "\." 来表示 |
小尖号(^) | 行首定位符,表示行首或否定,比如 "^48" ,即匹配以"48"开头的字符串,如"48 1 3 ..." ;若放在方括号内,比如"^[^48]",匹配不以"4"或"8"开头的任何字符串,如"1234" |
Dollar符($) | 行尾定位符,表示行尾,比如 "48$" ,即匹配以"48"结尾的字符串,如 "... 12 34 8 48" |
星号(*) | 表示前面的字符重复0~N次,比如 "8*" ,即匹配包含若干个8的字符串,如 "... 484..." 或者 "...5888.."等 |
方括号([...]) | 表示匹配方括号列表中的任一个,比如"[0-9a-z]",即匹配任何单个数字或字母,比如 "a" 或者 "1" ,注意区别 "[0-9][a-z]" ,它表示第一个是数字,接下来的字符是字母! |
大括号(\{m\}) | 表示前面的字符重复m次,比如"8\{2\}",即匹配包含"88"的字符串,比如"...1288.."等。另外 \{m,\}表示至少m次 ;\{m,n\}表示至少m次,不超过n次。 |
转意左尖括号(\<) | 词首定位符,表示匹配该词首的行,比如"\<92" ,即匹配行中包含以"92"开头的词,如"ab xy 92d aa" 和"9 d 92" |
转意右尖括号(\>) | 词尾定位符,和上面的相反,表示匹配该词尾的行 |
2、扩展的正则表达式的元素。
字符 | 意义和用法 |
---|---|
加号(+) | 表示重复前面的字符1~N次。例子嘛,类比上面的。 |
问号(?) | 表示重复前面的字符0或1次。也就是该字符最多出现1次。 |
竖线(|) | 用 or 的方式匹配多个字符串(注意,不是单个字符)。比如 "12|34",也就是匹配包含了"12" 或 "34"的字符串 |
括号((...)) | 表示字符组。比如"(12)+",意思是字符串中至少包含一个"12",比如 "...13124..." 或者 "...1212124..."。 |
[注意]
2) 在Linux各种工具如grep、awk中使用正则表达式,有细微的不同!详情见下面的解释。
3) 有四种元字符 \{ ,\}, \<, \> 各流派和工具对其支持程度不一!!使用时需格外注意!
二、find 命令
在 find 命令中,常见的用法如下,一般搜索文件名可以使用下面的命令:
比如:
find . -name "[a-z][0-9].txt" -print
这里的pattern(算不上是正则表达式)中特殊字符的含义如下:
? 文件名中的任意单个字符
[...] 匹配方括号内的任一字符
[!...] 不匹配方括号内的任一字符
[小结] 这里的 pattern 需要用引号引起来,避免误以为是shell 命令。
显然,这种用法是很局限的,但是通过加入正则表达式后就不一样了。用法如下:
find . -regex ".*\.\(txt\|sh\)"
使用 "-regex" 选项来表明 find 命令后面匹配的是正则表达式,用法上少许有些不同。
[解释] find 是在查找当前目录下以 .txt 和 .sh 结尾的文件;如果用 "-iregex" 表示忽略大小写。
[注意] 用 " -regex " 选项时,正则表达式中的所有特殊字符都需要转意!比如 "()" "|" "{}" 等。一般使用正则表达式时 "|" "(...)" 等是不需要转意的!
[其他]
如果觉得转移麻烦,也可以选择 "-regextype posix-egrep " 选项来扩展,比如:
find . -regextype posix-egrep -regex ".*\.(txt|sh)"如 "(...)" "{...}" 是不转意的! 这点上是和上面的规则稍有不同的!
二、grep 命令
grep 命令的常见使用方式如下:
grep [其他选项] '要搜索的字符串' 文件 比如: $ ls arr.dat avg.txt data data.f emp.data ip.sh loop.sh pwd select_sort.sh $ ls | grep '^i.*\.sh' ip.sh
[解释] grep命令的意思是查找当前目录下以字母"i"开头,以".sh"结尾的文件名。grep 有很多有用的选项,比如 "-n" "-v" "-i" 等。值得注意的是正则表达式要用单引号引起!
[其他] 如果希望使用扩展的regexp,则需要加上"-E" 选项。
比如:
grep -E '(219|216)+p' data.f
意思是查找类似于 "219pp" 之类的字符串。其中表示或关系的"|" 或 "+" 都是扩展正则表达式的内容!
[注意]:
{ } ( ) 代表本意,若想使用其特殊含义,则需转意!
grep -E 命令中,字符 . * ? + ^ $ [ ] | ( ) 都有特殊含义,如想使用本意,则需转意! 仅{ } 代表本意! 若想使用其特殊含义,则需转意!(有的工具不支持{})
例如:
grep '\(219\|216\)\+p' data.f
可以参考 man grep 中的内容,摘抄如下:
In basic regular expressions the meta-characters ?, +, {, |, (, and ) lose their special meaning; instead use the backslashed versions \?, \+, \{, \|, \(,and \).
Traditional egrep did not support the { meta-character, and some egrep implementations support \{ instead, so portable scripts should avoid { in grep -E patterns and should use [{] to match a literal {.
GNU grep -E attempts to support traditional usage by assuming that { is not special if it would be the start of an invalid interval specification. For example, the command grep -E '{1' searches for the two-character string {1 instead of reporting a syntax error
in the regular expression. POSIX.2 allows this behavior as an extension, but portable scripts should avoid it.
三、awk命令
awk 命令的常见用法如下:
awk '$1~/^123+\.txt/ { print $0 }' data.f
awk 中匹配(用"~")或者不匹配("!~") 一个正则表达式(必须放在"/..../"里)。上例的意思是 匹配字符串第一列满足 "以12开头,接着有至少一个'3',以'.txt'结尾的字符串 ",比如 "123333.txt"之类的。
[注意]:
中不支持字符 {...} 的特殊含义!
小结:特别注意转意字符的用法,什么时候要转意,什么时候不需要转意!
(全文完)