正则表达式
正则表达式,又称为规则表达式(Regular Expression,在代码中常简写为regex、regexp或RE),又称为模式模板(pattern template),用于描述字符串的某种特殊规则,它可以用来校验某个字符串是否满足该规则,或对符合该规则的字符串进行提取、删除、替换等操作。
常见应用
- 设置密码时:"请至少设置8位以上且同时包含数字、大小写字母和特殊字符"(限制用户所输入字符串的复杂度以提高密码强度)
- 从爬虫中提取有效手机号、邮箱号等有效信息
- 在Linux中配合sed、awk等命令进行文本处理
- ....
正则表达式的类型
正则表达式是通过正则表达式引擎(regular expression engine)实现的。正则表达式引擎是一套底层软件,负责解释正则表达式模式并对数据进行模式匹配,有两个主流的正则表达式引擎:
- 基础正则表达式(basic regular expression,BRE)引擎
- 扩展正则表达式(extended regular expression,ERE)引擎
传统的UNIX工具出于速度考虑,只支持BRE引擎规范,如果需要使用拓展正则表达式需要使用特殊选项,如:sed编辑器(根据不同版本使用-r或-E选项启用ERE),grep命令(使用-E选项启用ERE)
而现代的编程语言和工具基本都提供了支持ERE 语法的工具,如:Java的java.util.regex包、C语言的<regex.h>头文件、JavaScript、MySQL数据库等
语法
方括号 [ ]
方括号用于查找某个范围内的字符,括号内内容是或的关系
[a-z] 是否含有任意的小写字母
[A-Z] 是否含有任意的大写字母
[A-z] 是否含有任意字母
[0-9] 任意数字
a[bde]c 检查是否含有abc或adc或aec
与(&&)、或(|)、非(^)
逻辑运算符
与 &&
单个的&代表检测字符串中是否含有 “&” 这个符号,短路运算符&&才是将前后两个表达式做与运算
[a-z&&[def]] 仅匹配d或e或f字符
[a-z&[def]] 匹配a-z和&字符
[a-z&&[^m-p]] a-z且不包含m-p的集合(等同于[a-lq-z])
或 |
由于使用[ ]也表示逻辑或,因此当或符号位于 [ ] 内时 | 可以省略
a|b等同于[ab] 查询字符串内是否含有a或b字符
(\d|X|x)等同于[\dXx] 匹配身份证号最后一位(数字或者X、x),在Java中由于\转义,需要写为[\\dXx]
[a-c|e-g]可简写为[a-ce-g],也可写为[a-c[e-g]]
0[1-9]|1[0-2] 匹配月份01-09,10-12
0[1-9]|[12]\d|3[01] 匹配日期01-09,11-29,30,31
非 ^
取反运算
[^abc] 代表abc以外的任意字符
[a-z&&[^m-p]] a-z且不包含m-p的集合(等同于[a-lq-z])
量词
n? 0个或1个n
n?匹配只能包含0个或1个n的字符串,字符串中要么没有n,要么只能有一个n
let reg=/ab?c/; //只能匹配ac、abc
n* 0个、1个或多个n
n*匹配包含0个、1个或多个n的字符串,即有无n都可以,相当于{0,}n
let reg=/ab*c/; //匹配ac、abc、abbbbbc等b可有可无,或包含多个b的字符串
n+ 至少1个n
匹配包含至少有一个字符n的字符串,相当于{1,}n
let reg=/ab+c/; //匹配abc等b出现1次及1次以上的字符串
{x} 匹配出现x次的字符串
指定一个内容出现的次数,注意:它只对它之前的一个内容起作用,多个内容重复应该使用( )包裹
let reg=/a{3}/; //匹配aaa
let reg2=/ab{3}/; //匹配abbb
let reg3=/(ab){3}/; //匹配ababab
{x,y} 匹配出现x至y次的字符串
let reg=/ab{1,3}c/; //匹配abc、abbc、abbbc
{x,} 匹配出现的字符串大于等于x次的字符串
let reg=/ab{3,}c/; //匹配abbbc等b出现3次及3次以上的字符串
元字符与转义
元字符
元字符即正则表达式中一些用于特殊用途的字符
元字符 | 描述 |
---|---|
. | 查找单个任意字符,除了换行和行结束符 |
\w | 查找单词字符(任意字母、数字、下划线_) |
\W | 查找非单词字符(除字母、数字、下划线_以外的字符) |
\d | 查找数字 |
\D | 查找非数字字符 |
\s | 查找空白字符 |
\S | 查找非空白字符 |
\b | 匹配单词边界 |
\B | 匹配非单词边界 |
\o | 查找 NUL 字符(字符串结束字符) |
\n | 查找换行符 |
\f | 查找换页符 |
\r | 查找回车符 |
\t | 查找制表符 |
\v | 查找垂直制表符 |
\xxx | 查找以八进制数 xxx 规定的字符 |
\xdd | 查找以十六进制数 dd 规定的字符 |
\uxxxx | 查找以十六进制数 xxxx 规定的 Unicode 字符 |
转义字符
由于.*?+|^&\()[]{}字符已作为关键字使用,因此如匹配小数点等功能需要用到转义,正则表达式中使用\作为转义字符。此外,由于Java中的正则表达式规则以字符串形式表示,而字符串中\也为转义字符,因此往往需要两个转义字符\\进行二次转义,如:查找数字 \d,在Java的正则表达式中需要写为\\d,其他元字符同理。
let reg=/\./; //使用转义字符匹配字符串中的.号,如匹配小数点
字符串位置
常用位置
- ^n 匹配以 n 开头的字符串
- n$ 匹配以 n 结尾的字符串
- ^n|n$ 匹配以n开头或以n结尾的字符串
- ^n$ 以n开头马上以n结尾,因此只能匹配到"n"
- ?=n 匹配所有其后紧接指定字符串 n 的字符串,但不存储 n 的值
- ?:n 匹配所有其后紧接指定字符串 n 的字符串,并存储 n 的值
- ?!n 匹配所有其后没有紧接指定字符串 n 的字符串
let str="java自从95年问世以来,经历了很多版本,如:Java5,Java6...其中用的最多的是JAva8和JAva11,下一个长期支持版本是JAVA17";
let reg12=/java(?=8|11|17)/ig;
let reg13=/java(?:8|11|17)/ig;
let reg14=/java(?!8|11|17)/ig;
console.log(str.match(reg12)) //[ 'JAva', 'JAva', 'JAVA' ]
console.log(str.match(reg13)) //[ 'JAva8', 'JAva11', 'JAVA17' ]
console.log(str.match(reg14)) //[ 'java', 'Java', 'Java' ]
前瞻断言与后顾断言
- x(?=n) 查找n前的x(前瞻)
- (?<=n)x 查找n后的x(后顾)
- x(?!n) 查找后面不是n的x(负前瞻)
- (?<!n)x 查找前面不是n的x(负后顾)
import java.util.regex.Pattern;
public class RegexTest {
public static void main(String[] args) {
String str="java自从95年问世以来,经历了很多版本,如:Java5,Java6...其中用的最多的是JAva8和JAva11," +
"下一个长期支持版本是JAVA17";
String reg1="(?i)java(?:\\d*)";
String reg2="(?i)(?<=java)\\d*";
Pattern p1=Pattern.compile(reg1);
Pattern p2=Pattern.compile(reg2);
Matcher m1=p1.matcher(str);
Matcher m2=p2.matcher(str);
while(m1.find()){
System.out.println(m1.group());//java,Java5,Java6,JAva8,JAva11,JAVA17
}
System.out.println("------------M2");
while(m2.find()){
System.out.println(m2.group());// 5,6,8,11,17
}
}
}
单词边界
- \b 匹配一个单词边界
- \B 匹配一个非单词边界
当一个字符串本身刚好是另外一个字符串一部分时,如:child为children的一部分,需要使用单词边界来进行限定
let reg=/\bchild\b/;
console.log(reg.test("eg children")); //false
定义中单词的组成可以为字母、数字、下划线,即元字符中的\w,非单词为字母、数字、下划线以外的字符,即元字符中的\W。而边界为一个抽象的概念,并非实际字符,任意两个字符之间都可以视为一个边界。
\b用于匹配左右字符类型不相同的边界,即一边字符为\w,另一边字符为[^\w]
\B用于匹配左右字符类型相同的边界,即两边都是\w,或者两边都不是\w
let string=" at fat sat ate ato _at %at 9at %at& cate _at_ 0at0 ";
let re1=/.\bat\b./ig;
let re2=/.\Bat\b./ig;
let re3=/.\Bat\B./ig;
let re4=/.\bat\B./ig;
console.log(string.match(re1)) // [ ' at ', '%at ', '%at&' ]
console.log(string.match(re2)) // [ 'fat ', 'sat ', '_at ', '9at ' ]
console.log(string.match(re3)) // [ 'cate', '_at_', '0at0' ]
console.log(string.match(re4)) // [ ' ate', ' ato' ]
- 第一个正则表达式中,第一个\b由于右侧at属于\w,因此左侧只能为非\w的字符(包括空格符),第二个\b由于左侧at属于\w,因此右侧也只能为非\w的字符
- 第二个正则表达式中,表达式中\B由于右侧at属于\w,因此左侧也需要为属于\w的字符,表达式中\b由于左侧at属于\w,因此右侧只能为非\w的字符
- 第三个正则表达式中,第一个\B由于右侧at属于\w,因此左侧也需要为\w,第二个\B由于左侧at属于\w,因此右侧也需要为\w
- 第四个正则表达式中,\b由于右侧at属于\w,因此左侧只能为[^\w],\B由于左侧at属于\w,因此右侧也需要为\w
其他特殊符号同理
let string=" & a&a 0&0 #"
let re1=/.\b&\b./ig; //由于&为[^\w],因此&两侧都需要为\w
let re2=/.\B&\B./ig; //由于&为[^\w],因此&两侧都需要为[^\w]
console.log(string.match(re1)) // [ 'a&a', '0&0' ]
console.log(string.match(re2)) // [ ' & ', '#' ]
匹配模式
匹配模式可以忽略,默认情况下正则匹配会区分大小写,并且将在匹配到第一个结果后停止匹配并返回结果。正则表达式有六个参数用于指定匹配模式,这些参数既可以单独使用也可以任意顺序一起使用。
- g 全局搜索
- i 忽略大小写
- (?i) 忽略大小写(java)
- m 多行搜索
- s 允许.号匹配换行符
- u 使用unicode码的模式进行匹配。
- y 执行“粘性”搜索,匹配从目标字符串的当前位置开始。
a(?i)bc 忽略bc的大小写
a((?i)b)c 只忽略b的大小写
贪婪爬取与非贪婪爬取
贪婪爬取:尽可能多地爬取数据
非贪婪爬取:尽可能少地爬取数据,一般情况下
Java、JavaScript均默认为贪婪爬取,我们可以在数量词+、*后加上?将爬取模式修改为非贪婪爬取
package regex;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class MainTest {
public static void main(String[] args) {
String str="abbbbbbbbbbbcc";
//贪婪爬取
String reg1="ab+";
Pattern p1= Pattern.compile(reg1);
Matcher m1=p1.matcher(str);
while (m1.find()){
System.out.println(m1.group());//abbbbbbbbbbb
}
//非贪婪爬取
String reg2="ab+?";
Pattern p2= Pattern.compile(reg2);
Matcher m2=p2.matcher(str);
while (m2.find()){
System.out.println(m2.group());//ab
}
}
}
let str="abbbbbbbccccccccc";
let reg1=/ab+/g;
let reg2=/ab+?/g;
console.log(str.match(reg1)); //[ 'abbbbbbb' ]
console.log(str.match(reg2)); //[ 'ab' ]
捕获分组与非捕获分组
捕获分组
在正则表达式中,可以使用( )将语句分组,组号从1开始,分组以左括号为基准,最左边为第一组,其次为第二组,以此类推。
正则表达式内部调用
在正则表达式内部可以使用\组号将数据捕获出来,再次调用
(.+).+\1 匹配诸如 abc123abc、b45b 之类头尾相同的字符串
((.)\2*).+\1 匹配诸如 aa123aa 之类开头字符完全相同,且结尾字符等同于开头字符的字符串
正则表达式外部调用
在正则表达式外部可以使用$组号再次调用捕获的数据,如:在替换语句中调用捕获的数据,将重复的字符替换为单个字符
package regex;
public class outRegex {
public static void main(String[] args) {
String str="abbbccccccccdddddddd";
System.out.println(str.replaceAll("(.)\\1+","$1")); //abcd
}
}
非捕获分组
使用(?:)、(?:)、(?:)时,()仅用于囊括数据,无法通过\组号、$组号方式调用本组数据,并且非捕获分组不会占用组号
Java中的正则表达式
Java中的正则表达式规则以字符串形式表示,因此转义字符往往需要两个\\。此外,Java还提供了Pattern类和 Matcher类用于提供正则表达式支持。
String类与正则表达式有关的常用方法
public boolean matches(String regex)
返回boolean值,检测字符串是否匹配该正则表达式
package regex;
public class Matches {
public static void main(String[] args) {
String str="(&\\*)\\1{2}\\d+";
System.out.println("aaaa".matches(str)); //false
System.out.println("&*22".matches(str)); //false
System.out.println("&*&*&*222".matches(str)); //true
System.out.println("&*&*211".matches(str)); //false
}
}
public String replaceAll(String regex,String replacement)
返回一个String,将字符中所有满足该正则表达式的子字符串替换为指定内容。
与之类似的还有public String replaceFirst(String regex,String replacement),用给定的内容替换字符串中第一个满足该正则的子字符串
//字符去重
package regex;
public class RegexReplaceAll {
public static void main(String[] args) {
String str="abbbccccccccdddddddd";
System.out.println(str.replaceAll("(.)\\1+","$1"));
}
}
public String[] split(String regex)
返回一个String数组,按正则匹配的内容分割字符串,并将剩余内容返回为一个String数组
Pattern类与Matcher类
这两个类位于java.util.regex包下
Pattern(模式)类用于将正则表达式编译为此类的实例,即正则表达式的编译表示,该类的构造方法私有,需要通过调用其静态方法compile(String regex)来创建对象,将给定的正则表达式编译Pattern对象并返回,该类被final修饰,无法被继承。
Matcher(匹配器)类用于创建文本匹配器对象,执行匹配操作,该类也没有公共构造方法,需要通过Pattern对象的matcher(String)方法来获得一个Matcher对象,且该类也被final修饰,无法被继承。
Matcher类下常用的方法
- public boolean find() 搜索与正则匹配的目标字符串,返回boolean值
- public String group() 返回上一个匹配的字符串子序列
package regex;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 爬取所有带有java与其版本的信息
*/
public class PatternAndMatcher {
public static void main(String[] args) {
String str="java自从95年问世以来,经历了很多版本,如:Java5,Java6...其中用的最多的是JAva8和JAva11," +
"下一个长期支持版本是JAVA17";
String reg="(?i)java(?:\\d*)";
Pattern p= Pattern.compile(reg);
Matcher m=p.matcher(str);
while(m.find()){
System.out.println(m.group());//java Java5 Java6 JAva8 JAva11 JAVA17
}
}
}
JavaScript中的正则表达式
创建RegExp正则表达式对象
1.字面量
由斜杠/包围,语法:/正则表达式/匹配模式
let reg=/ab/i
2.利用构造函数
由引号“ 包围,语法:let 变量=new RegExp(“正则表达式”,”匹配模式”)
匹配模式可直接省略,默认情况下匹配到一个结果就返回
let reg=new RegExp("ab","i")
构造函数中的转义
由于构造函数中接收的参数为字符串,而字符串中\也为转义字符,因此在构造函数中使用\符号需要进行二次转义。如
let reg=new RegExp("\\."); //编译后的正则表达式为/\./,即用于匹配小数点
匹配字符串中是否有\
let reg=new RegExp("\\\\"); //编译后的正则表达式为/\\/
错误的语法
let reg=new RegExp("\\");
//编译后的正则表达式为/\/,表达式将\作为转义符号,转义后面的/符号,从而导致正则表达式缺少完整//符号而报错
测试字符串中是否有\完整代码
let reg=new RegExp("\\\\");
let str="abcd\\";
console.log(reg); //输出/\\/
console.log(str); //输出abcd\
console.log(reg.test(str)); //输出true
RegExp对象的常用方法
test()
在字符串中查找是否有满足正则表达式的值,有则返回true,无则返回false。
let reg=/hello/;
console.log(reg.test("xxhelloxx")); //true
在全局匹配模式下,同语句多次调用test()可能会出现返回的boolean值不同的情况
let reg=/^1[345678][0-9]{9}$/g;
console.log(reg.lastIndex,reg11.test("13456789000")) //0 true
console.log(reg.lastIndex,reg11.test("13456789000")) //11 false
这是由于RegRxp的lastIndex属性用于保存索引开始位置,第二个语句中lastIndex指向了11,解决方法为:
1. 不使用全局匹配
2. 在每次匹配前将lastIndex设置为0
let reg=/^1[345678][0-9]{9}$/g;
console.log(reg.lastIndex,reg.test("13228207602")) //0 true
reg.lastIndex=0;
console.log(reg.lastIndex,reg.test("13228207602")) //0 true
exec()
搜索出字符串中与正则表达式匹配的值,如果找到了,返回一个存放了匹配结果、匹配结果的第一个字符位置等信息的数组,如果未找到返回 null 。该方法不常用,搜索字符串常用String对象的match()方法。
String对象支持正则表达式的方法
split() 字符串拆分为数组
按所写正则表达式表达式规则将一个字符串拆分成数组,拆分处字符将丢弃,该方法即使不指定全局匹配,也会自动进行全局匹配,返回数据类型为Object数组。
var str="1a2b3c4d";
console.log(str.split(/[A-z]/));//返回['1','2','3','4']
search() 搜索匹配值
搜索字符串是否含有指定内容,有则返回第一次出现的索引值(即使为全局匹配也只返回第一次出现的索引值),没有则返回-1。返回数据类型为Number
var str="never forget ever";
console.log(str.search(/ever/));//返回1
console.log(str.search(/f/));//返回6
match() 找到一个或多个正则表达式匹配
将符合正则表达式的内容提取出来,默认情况下找到第一个符合的字符就会返回,因此经常配合全局匹配模式。返回数据类型为Object数组
var str="1a2b3c4d";
console.log(str.match(/[a-z]/ig));//返回['a','b','c','d']
console.log(str.search(/[0-9]/g));//返回['1','2','3','4']
replace() 将符合表达式的字符串替换成指定字符串
用于屏蔽、替换内容,接收两个参数:被替换的内容、新内容,语法为replace(字符或正则表达式,”新内容”)。默认只替换第一个符合表达式的内容。返回数据类型为String
var str="1a2b3c4d";
console.log(str.replace(/[a-z]/ig,"*"));//返回1*2*3*4*
console.log(str.replace(/[0-9]/g,""));//返回abcd
JavaScript去除空格
去除字符串中的所有空格
表达式:/\s/g
let str=" xxx xxx ";
let str1=str.replace(/\s/g,""); //输出xxxxxx
去除字符串前后的空格,保留字符之间的空格
表达式:/^\s+|\s+$/g若只去除前或后的空格,取表达式一半
let str=" xxx xxx ";
let str1=str.replace(/^\s+|\s+$/g,""); //输出xxx xxx
常用正则表达式
校验数字
1. 数字:^[0-9]*$ 2. n位的数字:^\d{n}$ 3. 至少n位的数字:^\d{n,}$ 4. m-n位的数字:^\d{m,n}$ 5. 零和非零开头的数字:^(0|[1-9][0-9]*)$ 6. 非零开头的最多带两位小数的数字:^([1-9][0-9]*)+(.[0-9]{1,2})?$ 7. 带1-2位小数的正数或负数:^(\-)?\d+(\.\d{1,2})?$ 8. 正数、负数、和小数:^(\-|\+)?\d+(\.\d+)?$ 9. 有两位小数的正实数:^[0-9]+(.[0-9]{2})?$ 10. 有1~3位小数的正实数:^[0-9]+(.[0-9]{1,3})?$ 11. 非零的正整数:^[1-9]\d*$ 或 ^([1-9][0-9]*){1,3}$ 或 ^\+?[1-9][0-9]*$ 12. 非零的负整数:^\-[1-9][]0-9"*$ 或 ^-[1-9]\d*$ 13. 非负整数:^\d+$ 或 ^[1-9]\d*|0$ 14. 非正整数:^-[1-9]\d*|0$ 或 ^((-\d+)|(0+))$ 15. 非负浮点数:^\d+(\.\d+)?$ 或 ^[1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0$ 16. 非正浮点数:^((-\d+(\.\d+)?)|(0+(\.0+)?))$ 或 ^(-([1-9]\d*\.\d*|0\.\d*[1-9]\d*))|0?\.0+|0$ 17. 正浮点数:^[1-9]\d*\.\d*|0\.\d*[1-9]\d*$ 或 ^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$ 18. 负浮点数:^-([1-9]\d*\.\d*|0\.\d*[1-9]\d*)$ 或 ^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$ 19. 浮点数:^(-?\d+)(\.\d+)?$ 或 ^-?([1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0)$
校验字符
1. 汉字:^[\u4e00-\u9fa5]{0,}$ 2. 英文和数字:^[A-Za-z0-9]+$ 或 ^[A-Za-z0-9]{4,40}$ 3. 长度为3-20的所有字符:^.{3,20}$ 4. 由26个英文字母组成的字符串:^[A-Za-z]+$ 5. 由26个大写英文字母组成的字符串:^[A-Z]+$ 6. 由26个小写英文字母组成的字符串:^[a-z]+$ 7. 由数字和26个英文字母组成的字符串:^[A-Za-z0-9]+$ 8. 由数字、26个英文字母或者下划线组成的字符串:^\w+$ 或 ^\w{3,20}$ 9. 中文、英文、数字包括下划线:^[\u4E00-\u9FA5A-Za-z0-9_]+$ 10. 中文、英文、数字但不包括下划线等符号:^[\u4E00-\u9FA5A-Za-z0-9]+$ 或 ^[\u4E00-\u9FA5A-Za-z0-9]{2,20}$ 11. 可以输入含有^%&',;=?$\"等字符:[^%&',;=?$\x22]+ 12 禁止输入含有~的字符:[^~\x22]+
信息
1. Email地址:^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$ 2. 域名:[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(/.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+/.? 3. InternetURL:[a-zA-z]+://[^\s]* 或 ^http://([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?$ 4. 手机号码:^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\d{8}$ 5. 电话号码("XXX-XXXXXXX"、"XXXX-XXXXXXXX"、"XXX-XXXXXXX"、"XXX-XXXXXXXX"、"XXXXXXX"和"XXXXXXXX):^(\(\d{3,4}-)|\d{3.4}-)?\d{7,8}$ 6. 国内电话号码(0511-4405222、021-87888822):\d{3}-\d{8}|\d{4}-\d{7} 7. 身份证号(15位、18位数字):^\d{15}|\d{18}$ 8. 短身份证号码(数字、字母x结尾):^([0-9]){7,18}(x|X)?$ 或 ^\d{8,18}|[0-9x]{8,18}|[0-9X]{8,18}?$ 9. 帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线):^[a-zA-Z][a-zA-Z0-9_]{4,15}$ 10. 密码(以字母开头,长度在6~18之间,只能包含字母、数字和下划线):^[a-zA-Z]\w{5,17}$ 11. 强密码(必须包含大小写字母和数字的组合,不能使用特殊字符,长度在8-10之间):^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,10}$ 12. 日期格式:^\d{4}-\d{1,2}-\d{1,2} 13. 一年的12个月(01~09和1~12):^(0?[1-9]|1[0-2])$ 14. 一个月的31天(01~09和1~31):^((0?[1-9])|((1|2)[0-9])|30|31)$ 15. 金额的输入格式: 1.有四种钱的表示形式我们可以接受:"10000.00" 和 "10,000.00", 和没有 "分" 的 "10000" 和 "10,000":^[1-9][0-9]*$ 2.这表示任意一个不以0开头的数字,但是,这也意味着一个字符"0"不通过,所以我们采用下面的形式:^(0|[1-9][0-9]*)$ 3.一个0或者一个不以0开头的数字.我们还可以允许开头有一个负号:^(0|-?[1-9][0-9]*)$ 4.这表示一个0或者一个可能为负的开头不为0的数字.让用户以0开头好了.把负号的也去掉,因为钱总不能是负的吧.下面我们要加的是说明可能的小数部分:^[0-9]+(.[0-9]+)?$ 5.必须说明的是,小数点后面至少应该有1位数,所以"10."是不通过的,但是 "10" 和 "10.2" 是通过的:^[0-9]+(.[0-9]{2})?$ 6.这样我们规定小数点后面必须有两位,如果你认为太苛刻了,可以这样:^[0-9]+(.[0-9]{1,2})?$ 7.这样就允许用户只写一位小数.下面我们该考虑数字中的逗号了,我们可以这样:^[0-9]{1,3}(,[0-9]{3})*(.[0-9]{1,2})?$ 8.1到3个数字,后面跟着任意个 逗号+3个数字,逗号成为可选,而不是必须:^([0-9]+|[0-9]{1,3}(,[0-9]{3})*)(.[0-9]{1,2})?$ 16. xml文件:^([a-zA-Z]+-?)+[a-zA-Z0-9]+\\.[x|X][m|M][l|L]$ 17. 中文字符的正则表达式:[\u4e00-\u9fa5] 18. 双字节字符:[^\x00-\xff] (包括汉字在内,可以用来计算字符串的长度(一个双字节字符长度计2,ASCII字符计1)) 19. 空白行的正则表达式:\n\s*\r (可以用来删除空白行) 20. HTML标记的正则表达式:<(\S*?)[^>]*>.*?\1>|<.*? /> (网上流传的版本太糟糕,上面这个也仅仅能部分,对于复杂的嵌套标记依旧无能为力) 21. 首尾空白字符的正则表达式:^\s*|\s*$或(^\s*)|(\s*$) (可以用来删除行首行尾的空白字符(包括空格、制表符、换页符等等),非常有用的表达式) 22. 腾讯QQ号:[1-9][0-9]{4,} (腾讯QQ号从10000开始) 23. 中国邮政编码:[1-9]\d{5}(?!\d) (中国邮政编码为6位数字) 24. IP地址:\d+\.\d+\.\d+\.\d+ (提取IP地址时有用) 25. IP地址:((?:(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d)\\.){3}(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d))