正则表达式和通配符¶
在 GNU/Linux 操作系统中,正则表达式和通配符经常使用相同的符号(或样式),因此人们常常混淆它们。
正则表达式和通配符有什么区别?
相似之处
- 它们使用相同的符号,但代表完全不同的含义。
区别
- 正则表达式匹配文件内容;通配符通常用于匹配文件名或目录名。
- 正则表达式通常用于 `grep`、`sed`、`awk` 等命令。
- 通配符通常用于 `cp`、`find`、`mv`、`touch`、`ls` 等命令。
GNU/Linux 中的通配符¶
GNU/Linux 操作系统支持这些通配符
| 通配符样式 | 作用 |
|---|---|
| ? | 匹配文件名或目录名中的一个字符。 |
| * | 匹配文件名或目录名中的零个或多个任意字符。 |
| [ ] | 匹配括号中的任何单个字符。例如,[one] 表示匹配 o 或 n 或 e。 |
| [-] | 匹配括号中给定范围内的任何单个字符。例如,[0-9] 匹配 0 到 9 之间的任何单个数字。 |
| [^] | 对单个字符进行“逻辑非”匹配。例如,[^a-zA-Z] 表示匹配任何非字母的单个字符。 |
| {,} | 非连续匹配多个单个字符。用逗号分隔。 |
| {..} | 与 [-] 相同。例如 {0..9} 和 {a..z} |
不同的命令对通配符样式的支持不同
- `find`: 支持 *, ?, [ ], [-], [^]
- `ls`: 全部支持
- `mkdir`: 支持 {,} 和 {..}
- `touch`: 支持 {,} 和 {..}
- `mv`: 全部支持
- `cp`: 全部支持
例如
Shell > mkdir -p /root/dir{1..3}
Shell > cd /root/dir1/
Shell > touch file{1,5,9}
Shell > cd
Shell > mv /root/dir1/file[1-9] /root/dir2/
Shell > cp /root/dir2/file{1..9} /root/dir3/
Shell > find / -iname "dir[1-9]" -a -type d
GNU/Linux 中的正则表达式¶
由于历史发展,存在两种主要的正则表达式体系
- POSIX
- BRE(基本正则表达式)
- ERE(扩展正则表达式)
- POSIX 字符类
- PCRE (Perl 兼容正则表达式): 在各种编程语言中最常见。
| BRE | ERE | POSIX 字符类 | PCRE | |
|---|---|---|---|---|
grep |
√ | √ (需要 -E 选项) |
√ | √ (需要 -P 选项) |
sed |
√ | √ (需要 -r 选项) |
√ | × |
awk |
√ | √ | √ | × |
有关正则表达式的更多信息,请访问 此网站 获取更多有用的信息。
BRE¶
BRE (Basic Regular Expression) 是最老的正则表达式类型,由 UNIX 系统中的 `grep` 命令和 **ed** 文本编辑器引入。
| 元字符 | 描述 | bash 示例 |
|---|---|---|
| * | 匹配前一个字符的出现次数,可以是 0 次或任意多次。 | |
| . | 匹配除换行符外的任何单个字符。 | |
| ^ | 匹配行首。例如 - **^h** 将匹配以 h 开头的行。 | |
| $ | 匹配行尾。例如 - **h$** 将匹配以 h 结尾的行。 | |
| [] | 匹配括号中指定的任何单个字符。例如 - **[who]** 将匹配 w 或 h 或 o; **[0-9]** 将匹配一个数字; **[0-9][a-z]** 将匹配由一个数字和一个小写字母组成的字符。 | |
| [^] | 匹配括号中除了指定字符以外的任何单个字符。例如 - **[^0-9]** 将匹配任何单个非数字字符。 **[^a-z]** 将匹配任何不是小写字母的单个字符。 | |
| \ | 转义字符,用于取消某些特殊符号所代表的含义。 | echo -e "1.2\n122" \| grep -E '1\.2'1.2 |
| \{n\} | 匹配前一个单个字符的出现次数,n 代表匹配的次数。 | echo -e "1994\n2000\n2222" \| grep "[24]\{4\}"2222 |
| \{n,\} | 匹配前一个单个字符至少出现 n 次。 | echo -e "1994\n2000\n2222" \| grep "[29]\{2,\}"1994 2222 |
| \{n,m\} | 匹配前一个单个字符至少出现 n 次,最多出现 m 次。 | echo -e "abcd\n20\n300\n4444" \| grep "[0-9]\{2,4\}"20 300 4444 |
ERE¶
| 元字符 | 描述 | bash 示例 |
|---|---|---|
| + | 匹配前一个单个字符的出现次数,可以是 1 次或更多次。 | echo -e "abcd\nab\nabb\ncdd" \| grep -E "ab+"abcd ab abb |
| ? | 匹配前一个单个字符的出现次数,可以是 0 次或 1 次。 | echo -e "ac\nabc\nadd" \| grep -E 'a?c'ac abc |
| \< | 边界字符,匹配字符串的开头。 | echo -e "1\n12\n123\n1234" \| grep -E "\<123"123 1234 |
| \> | 边界字符,匹配字符串的结尾。 | echo -e "export\nimport\nout" \| grep -E "port\>"export import |
| () | 组合匹配,即将括号中的字符串作为一个组合,然后进行匹配。 | echo -e "123abc\nabc123\na1b2c3" \| grep -E "([a-z][0-9])+"abc123 a1b2c3 |
| | | 管道符表示“或”的含义。 | echo -e "port\nimport\nexport\none123" \| grep -E "port\>\|123"port import export one123 |
ERE 还支持具有特殊含义的字符
| 特殊字符 | 描述 |
|---|---|
| \w | 等同于 **[a-zA-Z0-9]** |
| \W | 等同于 **[^a-zA-Z0-9]** |
| \d | 等同于 **[0-9]** |
| \D | 等同于 **[^0-9]** |
| \b | 等同于 **\<** 或 **\>** |
| \B | 匹配非边界字符。 |
| \s | 匹配任何空白字符。等同于 **[ \f\n\r\t\v]** |
| \S | 等同于 **[^ \f\n\r\t\v]** |
| 空白字符 | 描述 |
|---|---|
| \f | 匹配单个换页符。等同于 **\x0c** 和 **\cL** |
| \n | 匹配单个换行符。等同于 **\x0a** 和 **\cJ** |
| \r | 匹配单个回车符。等同于 **\x0d** 和 **\cM** |
| \t | 匹配单个制表符。等同于 **\x09** 和 **\cI** |
| \v | 匹配单个垂直制表符。等同于 **\x0b** 和 **\cK** |
POSIX 字符¶
有时,您可能会看到“POSIX 字符”(也称为“POSIX 字符类”)。请注意,作者很少使用“POSIX 字符类”,但已包含此部分以增强基本理解。
| POSIX 字符 | 等同于 |
|---|---|
| [:alnum:] | [a-zA-Z0-9] |
| [:alpha:] | [a-zA-Z] |
| [:lower:] | [a-z] |
| [:upper:] | [A-Z] |
| [:digit:] | [0-9] |
| [:space:] | [ \f\n\r\t\v] |
| [:graph:] | [^ \f\n\r\t\v] |
| [:blank:] | [ \t] |
| [:cntrl:] | [\x00-\x1F\x7F] |
| [:print:] | [\x20-\x7E] |
| [:punct:] | [][!"#$%&'()*+,./:;<=>?@^_`{|}~-] |
| [:xdigit:] | [A-Fa-f0-9] |
介绍正则表达式¶
网上有很多练习正则表达式技巧的网站,例如
作者:李天赐