基础

数量匹配

  • *代表{0,} +代表{1,} ?代表{0,1}

  • [0-9]+=[0-9]{1,} 表示匹配0~9中的任意数字,并且至少1位。

  • [0-9]*=[0-9]{0,} 表示匹配0~9中的任意数字,并且可以是0位(不存在)。

  • [0-9]?=[0-9]{0,1} 表示匹配0~9中的任意数字,并且只能是0位或1位。

  • 如果至少需要2位数,最多8位数,即([0-9]{2,7}) 。

  • 不写*、+、?和{m,n}表示只能出现一次

^的作用

只要是”^”这个字符是在中括号”[]”中被使用的话就是表示字符类的否定,如果不是的话就是表示限定开头
^A 会匹配”Axx”中的A,但是不会匹配”xxA”中的A —限定开头
[^a] 表示“匹配除了a的任意字符”。

$的作用

$表示限定结束

(.*?)详解

  • .是任意字符

  • .?是尽可能少的匹配(?跟在限制符后表示限制符的非贪婪模式)

  • (.?)是设置分组,如果替换、获取,可以用$1参数代替

示例探析

^\s*select\s[\s\S]*$

  • ^表示限定开头,(即表示开头必须是\s)

  • ^\s*则表示什么都不能有,除了空格(\s匹配任意的空白符,包括空格,制表符(Tab),换行符,中文全角空格)

  • select表示含有该字符

  • [\s\S]*表示所有字符都可以有,加了*表示可以出现0次(即可以什么都没有),不加则必须有任意字符,不能什么都没有(\S表示除空白符的所有字符,加上\s就表示所有字符)

  • [\b\B]同上

  • .也表所有字符,不过没有\s\S多

  • $表示限定结束,(即表示结束必须是[\s\S]*)

^\s*select\s+count\s*\(\s*(?:\\*|\w+)\s*\)[\s\S]*$

  • ^\s*select 表示开头必须是空白符或者空白符出现0次(即开头就是select)

  • \s+ 表示空白符至少一次

  • \(表示单纯的左括号(只是被转义了)

  • \( \s*(?:\\*|\w+)\s* \)表示括号里可以两边是空白符或没有;中间的(?:\\*|\w+) ?:表示只匹配但不获取匹配结果,为了优化;

  • [\s\S]*$ 表示结束可以是任意,包括什么都没有也行

[\s\S]+\s+where\s+[\s\S]+$

  • [\s\S]+\s+where 表示只能是 任意字符(1到多次)+空白符(1到多次)+where,而如果是\S+\s+where 表示只能是 非空白符(1到多次)+空白符(1到多次)+where。

  • 例如 a b where是不能被匹配到的。因为“ where”前面含有了空白符。

“abc|de|”.replaceAll(“(.*)\|”, “$1Java”)

  • Java的replaceAll方法,以上执行结果将是:abc|deJava,即匹配最后一个“|”。

  • “\|”表示为”|“这个特殊符号转义

  • “.*”表示任意字符可出现0次或多次,而*/+等默认都是贪婪模式,会尽可能多地匹配任意符号,故会将前一次的“|”也当做任意字符而不管,最后将只会匹配到“abc|de|”;而如果使用”(.*?)\|”,?跟在限制符后面表示非贪婪模式,将会尽可能少的匹配任意字符,那么匹配结果将是:“abc|”和“de|”。

  • “.*”加括号(.*)表示设置分组,如果替换、获取,可以用$1参数代替“.*”匹配到的结果(即abc|de)。以下是几个replaceAll的例子,可以更好理解:

    1
    "abc_d_d".replaceAll("_d","+Java")  // "ab+Java+Java",因为_d匹配结果是_d和_d(两个),故将_d替换为+Java
    1
    "abc_d_d".replaceAll(".*_d","+Java") // "+Java",因为.*_d匹配结果是abc_d_d,故将整个字符串替换为+Java
    1
    "abc_d_d".replaceAll("(.*)_d","$1+Java") // "abc_d+Java",因为(.*)_d匹配结果是abc_d_d,故将整个字符串替换为$1+Java,而$1表示被括号包裹的内容(即abc_d),故替换后为abc_d+Java
    1
    " abc_d_d".replaceAll(".*?_d","+Java") // "+Java+Java",因为.*?_d匹配结果是abc_d和_d,故将其均替换为+Java
    1
    "abc_def_d".replaceAll("(.*?)_d","$1+Java") // "abc+Javaef+Java",因为(.*?)_d匹配结果是abc_d和ef_d,故均将其替换为$1+Java,而abc_d的$1表示被括号包裹的内容(即abc),故替换后为abc+Java,而ef_d的$1表示被括号包裹的内容(即为ef),故替换后为ef+Java

我常用的

JS 时间字符串转时间

1
2
3
var str="20170818102656";
str=str.replace(/^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/g,"$1/$2/$3 $4:$5:$6");
var date=new Date(str);

去掉循环累加的分割符的最后一个(如,)

1
String result="a,b,c,d,e,".replaceAll("^([\\s\\S]+),", "$1");

给后缀名加时间,效果如:file20170506124530.jpg

1
String result = "xxx/cn/file.jpg".replaceAll("^([\\s\\S]+)(\\.\\w+)",$1" + DateTime.now().toString("yyyyMMddHHmmssSSS") + "$2");//DateTime.now()位于joda包。

拦截一些SQL语句

1
2
3
Pattern.matches("^\\s*select[\\s\\S]*$", " select * from user"//true
Pattern.matches("^\\s*select\\s+count\\s*\\(\\s*(?:\\*|\\w+)\\s*\\)\\s+[\\s\\S]+$", " select count(*) from user"//true
"select * from user gourp by user.classid".matches("[\\s\\S]+\\s+gourp\\s+by\\s+[\\s\\S]+$") //true