1、前言
最近因经常需对基因组注释文件gff3的基因id替换或更改,需要用到正则表达式。资料里面都提到:*匹配前面的子表达式0次或任意多次。我当时就纳闷,*到底是表示的是匹配的次数还是可以匹配任意字符呀?因为印象中,*也可以匹配任意字符。
后面才弄明白自己混淆了正则表达式与通配符,*在正则表达式和通配符中的含义是不一样的。
类似的还有字符:?
2、正则表达式与通配符使用场景
总结就是:正则表达式主要用于shell脚本(正则表达式主要用来匹配文件中的字符串,主要操作有grep、awk、sed。简单来说),而通配符主要用于shell命令行(命令行ls、find、cp、mv等)。
3、正则表达式与通配符具体的使用区别
3.1通配符的基本用法
通配符主要用于shell命令行中。常见的匹配规则有:
ls *
会列出当前目录下所有文件,*
匹配了所有的文件名,而ls *a
匹配所有a开头的文件。
需要注意的是,如果当前目录下有目录名匹配成功,会列出该目录下所有文件
*
可以代替任意个数字符,?
只能代替一个。
通配符主要用法
通配符 含义 举例
* 匹配0或多个任意字符 a*匹配a开头的任意文件
? 匹配任意单个字符 a?.txt可以匹配ab.txt,ac.txt,但是不能匹配abc.txt
[] 匹配括号中任意字符
[abc].txt可以匹配a.txt 、b.txt、 c.txt
[!] 匹配不在括号中的任意字符 [!abc]*可以匹配不宜abc开头的任意文件
[a-z] 匹配a-z的任意单个字符,只能用于查找文件不能用于创建文件 [a-z]*匹配a-z开头的任意文件
{a,b,z} 逗号分隔表示单个字符,可用于创建和查找文件 {a,b,z}*表示以a或b或z开头的任意文件
{a..z} ..分隔表示连续字符,表示范围 {a..z}*表示任意小写字母开头的文件
特别需要说明的是:
由于上面表中的一些字符,如*?[]等字符具有特殊的含义(用法),例如,*并不是代表这个字符本身,而是代表任意字符,因此如果需要匹配*本身,需要转义。转义用\表示,如
\*表示*本身,\*abc 可以匹配字符串 "*abc"
3.2 shell Meta字符(元字符)
shell 除了有通配符之外,还有一系列自己的其他特殊字符。
|------|-------------------------------------------------------|
| 字符 | 说明 |
| IFS | 由 <space> 或 <tab> 或 <enter> 三者之一组成(我们常用 space ) |
| CR | 由 <enter> 产生 |
| = | 设定变量 |
| $ | 取变量值或取运算值 |
| > | 重定向 stdout |
| < | 重定向 stdin |
| | | 管道符号 |
| & | 重导向 file descriptor ,或将命令置于背景执行 |
| ( ) | 将其内的命令置于 nested subshell 执行,或用于运算或命令替换 |
| { } | 将其内的命令置于 non-named function 中执行,或用在变量替换的界定范围 |
| ; | 在前一个命令结束时,而忽略其返回值,继续执行下一个命令 |
| && | 在前一个命令结束时,若返回值为 true,继续执行下一个命令 |
| || | 在前一个命令结束时,若返回值为 false,继续执行下一个命令 |
| ! | 运算意义上的非(not)的意思 |
| # | 注释,常用在脚本中 |
| \ | 转移字符,去除其后紧跟的元字符或通配符的特殊意义 |
3.3 正则表达式的基本用法
正则表达式主要用于shell脚本中。常见用法如下:
正则表达式的主要用法
元字符 含义 用法举例
() 表示一个字表达式,括号内是一个整体(配合sed命令,则打印括号中的内容)
* 前一个子表达式或字符匹配0或任意多次
ab*可以匹配a、ab、abb、abbb等
h(ab)*可以匹配h或hab或habab
? 前一个子表达式或字符匹配0或1次 h(ab)*可以匹配h或hab,不能匹配habab
- 前一个子表达式1次或以上,扩展正则表达式 ----\([0-9]\+\)---"[0-9]\+"表示一串数字
. 匹配出换行符\n之外的任意单个字符
[] 匹配括号中任意一个指定字符,只匹配一个字符 [aeiou]可以匹配google中的o e
[^] 匹配不再括号中的任意一个字符
^ 匹配行首(当不位于[]内时) ^hello匹配hello开头的字符串
$ 匹配行尾
\ 转义字符,取消特殊含义 \可以匹配字符*,此时*不再表示匹配次数
{n} 表示前面的字符恰好n次
{n,} 表示前面的字符最少出现n次
{n,m} 表示前面的字符出现n~m次
\1 引用第一个左括号以及与之对应的右括号所包括的所有内容,\2同理
同通配符的规则,一样,匹配上面表中的特殊字符(元字符)时,也需要转义:
例如\*表示*这个字符本身,次数*不再表示前面的字符可以出现的次数为任意次。
\ ----正则表达式中的反斜杠的用法
字符 描述
\b 匹配一个单词边界,也就是指单词和空格间的位置。例如,"er\b"可以匹配"never"中的"er",但不能匹配"verb"中的"er"。
\B 匹配非单词边界。"er\B"能匹配"verb"中的"er",但不能匹配"never"中的"er"。
\cx 匹配由x指明的控制字符。例如,\cM匹配一个Control-M或回车符。x的值必须为A-Z或a-z之一。否则,将c视为一个原义的"c"字符。
\d 匹配一个数字字符。等价于[0-9] 。
\D 匹配一个非数字字符。等价于[^0-9]。
\f 匹配一个换页符。等价于\x0c和\cL。
\n 匹配一个换行符。等价于\x0a和\cJ。
\r 匹配一个回车符。等价于\x0d和\cM。
\s 匹配任何空白字符,包括空格、制表符、换页符等等。等价于[ \f\n\r\t\v]。
\S 匹配任何非空白字符。等价于[^ \f\n\r\t\v]。
\t 匹配一个制表符。等价于\x09和\cI。
\v 匹配一个垂直制表符。等价于\x0b和\cK。
\w 匹配包括下划线的任何单词字符。等价于"[A-Za-z0-9_]"。
\W 匹配任何非单词字符。等价于"[^A-Za-z0-9_]"。
\xn 匹配n,其中n为十六进制转义值。十六进制转义值必须为确定的两个数字长。例如,"\x41"匹配"A"。"\x041"则等价于"\x04&1"。正则表达式中可以使用ASCII编码。.
\num 向后引用(back-reference)一个子字符串(substring),该子字符串与正则表达式的第num个用括号围起来的子表达式(subexpression)匹配。其中num是从1开始的正整数,其上限可能是99。例如:"(.)\1"匹配两个连续的相同字符。
\n 标识一个八进制转义值或一个向后引用。如果\n之前至少n个获取的子表达式,则n为向后引用。否则,如果n为八进制数字(0-7),则n为一个八进制转义值。
\nm 标识一个八进制转义值或一个向后引用。如果\nm之前至少有nm个获得子表达式,则nm为向后引用。如果\nm之前至少有n个获取,则n为一个后跟文字m的向后引用。如果前面的条件都不满足,若n和m均为八进制数字(0-7),则\nm将匹配八进制转义值nm。
\nml 如果n为八进制数字(0-3),且m和l均为八进制数字(0-7),则匹配八进制转义值nml。
\un 匹配n,其中n是一个用四个十六进制数字表示的Unicode字符。例如,\u00A9匹配版权符号
4.awk print与printf的差别
awk中如果输出字符的话,有两种处理方式。printf和print,两种方式存在着不同,下面简要的说明下。
printf:可以自定义输出的模式,另外输出内容之后不自动换行
print:输出内容之后自动换行
example:
file
11111_22222_33333_44444_55555_66666
awk -F'_' '{for(i=1;i<=NF;i++)print $i}' file
11111
22222
33333
44444
55555
66666
awk -F'_' '{for(i=1;i<=NF;i++)printf $i}' file
111112222233333444445555566666
所以可以看出,print输出一个内容之后,自动换行,但是printf不会这样,另外如果我们需要在处理文本的过程中输出换行符的话,可以print "",输出一个空字符就表示输出了一个换行符