java 正则表达式详细

来源:互联网 发布:汨罗淘宝售后打包招聘 编辑:程序博客网 时间:2024/05/17 04:37
import java.util.regex.Matcher;import java.util.regex.Pattern;public class Test {public static void main(String[] args) {// 简单认识正则表达式的概念p("abc".matches("...")); // 一个.代表一个字符/* * \d代表一位数字,用\\d是因为java有转义字符\"等,但是没有\d这种转义字符, 会报错, * java看到\就会判断你是哪种转义字符,不是转义字符就会报错 */p("a789b".replaceAll("\\d", "-"));/* * java.util.prefs.Pattern没有构造方法, *  用它的静态的compile(String regex)方法, * 代表把这种正则表达式编译一下,放入Pattern(模式)中, *  首先编译好匹配效率高,每次重新编译效率底 */Pattern pa = Pattern.compile("[a-z]{3}"); // 三个字符,每个字符在a-z之间Matcher m = pa.matcher("abc");//调用本方法去匹配某个字符串p(m.matches());//调用本方法查看匹配的结果/* * 这句话相当于上面的三句话,可是这句话执行的 * 时候还要先编译模式再执行,效率没有上面高 * 这句话也调用不到Pattern和Matcher的其他方法 */p("abc".matches("[a-z]{3}")); /* * .代表一个字符,*代表0个或多个字符, * 也有正常的字符,比如模式中是aa,那么表示字母是aa的, * 注意这里不是前两位是aa的,一定是多有位字母都一样, * +代表一个或多个,?代表一个或0个 */p("a".matches("."));p("aaa".matches("aa"));//和aaa匹配的是aaa不是aa,aa不代表aa开头p("aaaa".matches("a*"));p("aaaa".matches("a+"));p("".matches("a*"));p("".matches("a?"));p("aaaa".matches("a?"));//和aaaa匹配的是aaaa不是a?,a?代表aa或""或a,并不是这个字符打头p("12156165156165".matches("\\d{3,100}"));p("192.168.0.1".matches("\\d{0,3}\\.\\d{0,3}\\.\\d{0,3}\\.\\d{0,3}"));//{0,3}包含0和3p("192".matches("[0-2][0-9][0-9]"));//[0-2]包含0和2/* * 范围: * [abdnsjbdbsa]代表的是匹配一个字符包含在[abdnsjbdbsa]之中, * 一个[]代表匹配一个字符[a-zA-Z]表示这个字符在a-z和A-Z之间 * [a-zA-Z]这里zA中间不用加别的也可以写成[a-z]|[A-Z]还可以写成[a-z[A-Z]], * [^abc]取反,除了abc的,[A-Z&&[ABC]]代表是A-Z之中的并且是ABC之间的 */p("a".matches("[abc]"));p("a".matches("[^abc]"));p("A".matches("[a-zA-Z]"));p("A".matches("[a-z]|[A-Z]"));p("A".matches("[a-z[A-Z]]"));p("N".matches("[A-Z&&[NMZ]]"));//这种方法去不到&&的取不到N!,目前只知道p("N".matches("[A-Z&&[NMZ]]"));这种方法p("N".matches("[A-Z]&&[NMZ]"));/* * 认识\s \w \d \ * 正则表达式本身也用\后边跟东西表示某些范围, * 所以正则表达式中\用\\表示, * 但是如果和java的\比较时,在"\\".matches("\\\\"); * 方法中"\\"代表了java的一个反斜线, * 但是后面方法里要求传一个正则表达式模式的\, * 但是正则表达式中用\\表示一个\,如果方法参数是\\的话, * 在正则表达式中为\,传入方法后参数也就是\了,就报错了, * 传入方法的应该是java中的\\,在正则表达式中就是\\\\, * 这里是特别绕的 * \d数字:[0-9] * \D非数字: [^0-9] * \s空白字符:[ \t\n\x0B\f\r] * \S非空白字符:[^\s] * \w单词字符:[a-zA-Z_0-9] * \W非单词字符:[^\w] */p(" \n\r\t".matches("\\s{4}"));p(" ".matches("\\S"));p("a_8".matches("\\w{3}"));p("abc888&^%".matches("[a-z]{1,3}\\d{3}\\W{3}"));p("abc888&^%".matches("[a-z]{1,3}\\d+[&^#%]+"));p("\\".matches("\\\\"));//POSIX Stylep("a".matches("\\p{Lower}"));//边界处理(开头结尾的处理)p("hello sir".matches("^h.*"));p("hello sir".matches(".*ir$"));p("hello sir".matches("^h[a-z]{1,3}o\\b.*"));p("hellosir".matches("^h[a-z]{1,3}o\\b*"));//找空白行p(" \n".matches("^[\\s&&[^\\n]]*\\n$"));//匹配Emailp("123456789@qq.com".matches("[\\w[.-]]+@[\\w[.-]]+\\.[\\w[.-]]+"));/* * matches find lookingAt * matches永远是匹配整个字符串,但是matches方法匹配的时候, * 比如匹配到第5个字符不匹配,就不会退回去了, * 匹配位置就走到第5个了,find方法是匹配有没有子串, * matches和find用时会有影响,调用reset方法把匹配位置重新弄到第一个, * find一下就代表找一个字串,然后位置就到那, * find第二次就接着从第一次往下的位置开始找,lookingAt方法也是找字串, * 但是每次lookingAt都是从字符串开始处找 */Pattern p1 = Pattern.compile("\\d{3,5}");String s1 = "012-23561-265-00";Matcher m1 = p1.matcher(s1);p(m1.matches());m1.reset();p(m1.find());//返回找到的字串的起始位置和结束位置,start返回起始的位置,end返回结束的后一个位置p(m1.start() + "-" + m1.end()); p(m1.find());//返回找到的字串的起始位置和结束位置,start返回起始的位置,end返回结束的后一个位置p(m1.start() + "-" + m1.end());p(m1.find());//返回找到的字串的起始位置和结束位置,start返回起始的位置,end返回结束的后一个位置p(m1.start() + "-" + m1.end()); p(m1.find());//返回找到的字串的起始位置和结束位置,这里没找到会报错,用if判断上面的find方法//p(m1.start() + "-" + m1.end()); p(m1.lookingAt());p(m1.lookingAt());p(m1.lookingAt());p(m1.lookingAt());/* * replace * 在调用Pattern.compile(String regex, int flags)方法时, * 还可以指定一个匹配标志,这些标志是Pattern的静态常量, * 然后循环调用Matcher对象的find方法可以找一个一个的字串, * 接着调用Matcher对象的group()方法,可以返回由以前匹配操作 * 所匹配的输入子序列,调用replaceAll(String replacement) * 方法可以替换模式(定义的模式)与给定替换字符串(模式检测的字符串) * 相匹配的输入序列的每个子序列。 */Pattern p2 = Pattern.compile("java", Pattern.CASE_INSENSITIVE);Matcher m2 = p2.matcher("java Java JAva JAVA IloveJAVa  asasas");/* * 找是否有忽略大小的子串while(m2.find()) {p(m2.group());}*///全部替换大写p(m2.replaceAll("JAVA"));/* * 这里我想找到的单数用小写,找到的双数用大写 */StringBuffer sb = new StringBuffer();int index = 0;while(m2.find()) {index ++;if(index % 2 ==0) {//找到位置并替换放入StringBuffer中,前后不替换的字符串也会跟着加进去m2.appendReplacement(sb, "JAVA");} else {m2.appendReplacement(sb, "java");}}/* * 用来添加appendReplacement后剩余的字符串, * 自己的程序中尚不需要(不知道怎么回事) * m2.appendTail(sb); */p(sb);/* * 正则表达式的匹配模式在定义的时候可以分组,分组用小括号来定义, * 当小括号嵌套时,数左小括号,第几个就是第几组, * 这样在找到这样模式的字串之后,就可以通过group(int 组号) * 的方式取得当前组的值,传0或者调用重载的无参数的group方法就 * 是打印整个大组的值 */Pattern p3 = Pattern.compile("(\\d{3,5})([a-z]{2})");String s2 = "012aa-56565vv-3649rr-99";Matcher m3 = p3.matcher(s2);while(m3.find()) {p(m3.group(1));}/* * qulifiers * 这段程序Greedy("(.{3,10})[0-9]")在匹配的时候, * 首先一看最多10个字符就直接吞进去10个字符, * 然后和整个的正则表达式做匹配,发现如果只匹配(.{3,10}) * 后面还有个[0-9],这样不匹配,所以它吐出一个来, * 然后再匹配,就匹配上了但是Reluctant("(.{3,10}?)[0-9]") * 的在匹配的时候,吞最少的,首先吞进去三个,然后和整个模式匹配, * 发现后面一位不是数字,再吞一个,发现匹配了,他就结束了, * Possessive("(.{3,10}+)[0-9]")和Greedy差不多,都是吞最多的, * 但是不吐,注意这里用了组是为的看的更清楚, * 千万注意的是不要把Possessive("(.{3,10}+)[0-9]")和 * Greedy("(.+)[0-9]")混淆("(.{3,10}+)[0-9]")这个在Greedy * 中是("(.{3,10})[0-9]")而("(.+)[0-9]")这个在Possessive中是 * ("(.++)[0-9]" */Pattern p4 = Pattern.compile("(.{3,10})[0-9]");Matcher m4 = p4.matcher("aaaa5bbbb9");if(m4.find()) {p(m4.start() + "-" + m4.end());}else {p("没找到可以匹配的");}/* * 特殊构造(非捕获)这个要自己试,很绕很“诡异” * (?:X)X,作为非捕获组 * (?idmsux-idmsux) Nothing,但是将匹配标志i d m s u x on - off * (?idmsux-idmsux:X)  X,作为带有给定标志 i d m s u x on - off的非捕获组  * (?=X)X,通过零宽度的正 lookahead * (?!X)X,通过零宽度的负 lookahead * (?<=X)X,通过零宽度的正 lookbehind * (?<!X)X,通过零宽度的负 lookbehind * (?>X)X,作为独立的非捕获组 * 用的最多的是(?=X),加在后面不捕获,加在前面捕获 */Pattern p5 = Pattern.compile(".{3}(?=a)");String s5 = "123a46b";Matcher m5 = p5.matcher(s5);while(m5.find()) {p(m5.group());}/* * 向前引用 * \\2的意思是我后面的数必须和第二组相同 *  \\1的意思是我后面的数必须和第一组相同 */Pattern p6 = Pattern.compile("(\\d(\\d))\\2");Matcher m6 = p6.matcher("122");p(m6.matches());/* * flags的简写 * 打开静态常量可以找到简写形式 */Pattern p7 = Pattern.compile("java", Pattern.CASE_INSENSITIVE);p("JAVa".matches("(?i)(java)"));}public static void p(Object o) { // 简化打印方法System.out.println(o);}}