java正则表达式教程(翻译)
2016-12-12 17:31
1326 查看
翻译至:http://www.vogella.com/tutorials/JavaRegularExpressions/article.html
正则表达式可以用于搜索,编辑和处理文本。
利用正则表达式分析或修改文本的过程被称为:正则表达式应用于文本/字符串。正则表达式定义的模式是从左到右应用于文本的。一旦一个源字符已经被匹配了,它就不能被重新匹配。例如,正则表达式aba将只匹配ababababa两次(aba_aba_)。
下面列出了几个正则表达式,并描述了它们匹配的模式。
表一:正则表达式的例子
下面是一些通过JUnit验证的例子。如果您不想用JUnit的话,可以自己调整一下。要了解JUnit,请参考JUnit教程
此外,这些分组中也可以使用反向引用。反向引用可以储存匹配到的一个组,它可以用于后面的替换操作。
通过$可以指定一组。$1表示组1,$2表示组2,以此类推。
例如,假设你要替换一个字母后跟一个点或逗号之间的所有空格。
(?i) 表示不区分大小写
(?s) 单行模式,使.匹配所有字符,包括换行符。
(?m) 多行模式,使得每一行都插入脱字符^和结束符$
但是这些方法都没有优化性能。
类:
测试类:
\b表示词边界,而\1表示第一组匹配到的内容。
(?!-in)\b(\w+) \1\b 匹配不以-in开头的重复单词。
提示:可以添加(?s)进行多行匹配。
对应的正则表达式
目标可以是你的例子
1、正则表达式
1.1、什么是正则表达式?
一个正则表达式定义了一个字符串的搜索模式。正则表达式的简称为正则。搜索模式可以是一个简单的字符,一个固定的字符串或是一个包含特殊字符描述的复杂模式。模式定义的正则表达式可以匹配一个给定的字符串0次或多次。正则表达式可以用于搜索,编辑和处理文本。
利用正则表达式分析或修改文本的过程被称为:正则表达式应用于文本/字符串。正则表达式定义的模式是从左到右应用于文本的。一旦一个源字符已经被匹配了,它就不能被重新匹配。例如,正则表达式aba将只匹配ababababa两次(aba_aba_)。
1.2、正则表达式的例子
一个简单的正则表达式是一个(文字的)字符串。例如,正则表达式hello world匹配字符串hello world。另一个正则表达式的例子是.字符。一个.匹配任何单个字符,例如,它能匹配a或1。下面列出了几个正则表达式,并描述了它们匹配的模式。
正则表达式 | 匹配 |
---|---|
this is text | 匹配this is text |
this\s+is\s+text | 匹配这样的句子:this后接一个或多个空格,后面接上is,后面再接上一个或多个空格,再接上text |
^\d+(\.\d+)? | 定义一个必须以新的一行开始的模式。 \d匹配一个或多个数字。?号表示括号里面的内容是可选的。\.表示英文句号,()是用于分组。例如,它会匹配5、1.5和2.21 |
1.3、支持正则表达式的变成语言
正则表达式被大多数编程语言所支持,例如,java,perl,Grovy等都支持。遗憾的是,每种语言支持的正则表达式略有不同。2、先决条件
以下的课程中,需要你已经有了java基础。下面是一些通过JUnit验证的例子。如果您不想用JUnit的话,可以自己调整一下。要了解JUnit,请参考JUnit教程
3、正则表达式语法
3.1、常见的匹配符号
3.2、元字符
3.3、量词
3.4、分组和反向引用
你可以把你的正则表达式进行分组。可以在你的正则表达式中用()来分组,这允许你去指定一个可以重用的组。此外,这些分组中也可以使用反向引用。反向引用可以储存匹配到的一个组,它可以用于后面的替换操作。
通过$可以指定一组。$1表示组1,$2表示组2,以此类推。
例如,假设你要替换一个字母后跟一个点或逗号之间的所有空格。
//去空格 // Removes whitespace between a word character and . or , String pattern = "(\\w)(\\s+)([\\.,])"; System.out.println("abc ,123 .".replaceAll(pattern, "$1$3"));
//提取标题之间的文本 // Extract the text between the two title elements String pattern = "(?i)(<title.*?>)(.+?)()"; String updated = "<title='dd'>标题".replaceAll(pattern, "$2");
3.5、否定式向前匹配
否定式向前匹配提供了排除某种模式的可能性。它的定义为(?!pattern)。例如,a(?!b)匹配一个后面没有接一个b的字符a。既匹配ac中的a,但不匹配ab中的a。3.6、在正则表达式中替代模式
你可以在正则表达式的开头添加模式修饰符。若要使用多种模式,可以这样写(?ismx)(?i) 表示不区分大小写
(?s) 单行模式,使.匹配所有字符,包括换行符。
(?m) 多行模式,使得每一行都插入脱字符^和结束符$
3.7、java中的反斜杠\
反斜杠是java中的转义字符。这说明反斜杠在java中有预定义的作用。你必须使用两个反斜杠\\来表示一个反斜杠\。如果你要定义\w的话,你的正则表达式需要这样写\\w。如果你想让反斜杠表示一个文字,你需要输入\\\\。4、在String的方法中使用正则表达式
4.1、解释String中处理正则表达式的方法
Java内置的String类支持正则表达式。String类有四个内置的方法支持正则表达式,分别是matches(),split(),replaceFirst()和replaceAll()。但replace()不支持正则表达式。但是这些方法都没有优化性能。
package de.vogella.regex.test; public class RegexTestStrings { public static final String EXAMPLE_TEST = "This is my small example " + "string which I'm going to " + "use for pattern matching."; public static void main(String[] args) { System.out.println(EXAMPLE_TEST.matches("\\w.*")); String[] splitString = (EXAMPLE_TEST.split("\\s+")); System.out.println(splitString.length);// should be 14 for (String string : splitString) { System.out.println(string); } // replace all whitespace with tabs System.out.println(EXAMPLE_TEST.replaceAll("\\s+", "\t")); } }
4.2、例子
String正则表达式的例子类:
package de.vogella.regex.string; public class StringMatcher { // returns true if the string matches exactly "true" public boolean isTrue(String s){ return s.matches("true"); } // returns true if the string matches exactly "true" or "True" public boolean isTrueVersion2(String s){ return s.matches("[tT]rue"); } // returns true if the string matches exactly "true" or "True" // or "yes" or "Yes" public boolean isTrueOrYes(String s){ return s.matches("[tT]rue|[yY]es"); } // returns true if the string contains exactly "true" public boolean containsTrue(String s){ return s.matches(".*true.*"); } // returns true if the string contains of three letters public boolean isThreeLetters(String s){ return s.matches("[a-zA-Z]{3}"); // simpler from for // return s.matches("[a-Z][a-Z][a-Z]"); } // returns true if the string does not have a number at the beginning public boolean isNoNumberAtBeginning(String s){ return s.matches("^[^\\d].*"); } // returns true if the string contains a arbitrary number of characters except b public boolean isIntersection(String s){ return s.matches("([\\w&&[^b]])*"); } // returns true if the string contains a number less then 300 public boolean isLessThenThreeHundred(String s){ return s.matches("[^0-9]*[12]?[0-9]{1,2}[^0-9]*"); } }
测试类:
package de.vogella.regex.string; import org.junit.Before; import org.junit.Test; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; public class StringMatcherTest { private StringMatcher m; @Before public void setup(){ m = new StringMatcher(); } @Test public void testIsTrue() { assertTrue(m.isTrue("true")); assertFalse(m.isTrue("true2")); assertFalse(m.isTrue("True")); } @Test public void testIsTrueVersion2() { assertTrue(m.isTrueVersion2("true")); assertFalse(m.isTrueVersion2("true2")); assertTrue(m.isTrueVersion2("True"));; } @Test public void testIsTrueOrYes() { assertTrue(m.isTrueOrYes("true")); assertTrue(m.isTrueOrYes("yes")); assertTrue(m.isTrueOrYes("Yes")); assertFalse(m.isTrueOrYes("no")); } @Test public void testContainsTrue() { assertTrue(m.containsTrue("thetruewithin")); } @Test public void testIsThreeLetters() { assertTrue(m.isThreeLetters("abc")); assertFalse(m.isThreeLetters("abcd")); } @Test public void testisNoNumberAtBeginning() { assertTrue(m.isNoNumberAtBeginning("abc")); assertFalse(m.isNoNumberAtBeginning("1abcd")); assertTrue(m.isNoNumberAtBeginning("a1bcd")); assertTrue(m.isNoNumberAtBeginning("asdfdsf")); } @Test public void testisIntersection() { assertTrue(m.isIntersection("1")); assertFalse(m.isIntersection("abcksdfkdskfsdfdsf")); assertTrue(m.isIntersection("skdskfjsmcnxmvjwque484242")); } @Test public void testLessThenThreeHundred() { assertTrue(m.isLessThenThreeHundred("288")); assertFalse(m.isLessThenThreeHundred("3288")); assertFalse(m.isLessThenThreeHundred("328 8")); assertTrue(m.isLessThenThreeHundred("1")); assertTrue(m.isLessThenThreeHundred("99")); assertFalse(m.isLessThenThreeHundred("300")); } }
5、Pattern和Matcher
对于高级的正则表达式类java.util.regex.Pattern和java.util.regex.Matcher。首先创建一个定义了正则表达式的Pattern对象。这个对象允许你为给定的字符串创建一个Matcher对象,这个Matcher对象允许你去对一个字符串进行正则表达式的操作。package de.vogella.regex.test; import java.util.regex.Matcher; import java.util.regex.Pattern; public class RegexTestPatternMatcher { public static final String EXAMPLE_TEST = "This is my small example string which I'm going to use for pattern matching."; public static void main(String[] args) { Pattern pattern = Pattern.compile("\\w+"); // in case you would like to ignore case sensitivity, // you could use this statement: // Pattern pattern = Pattern.compile("\\s+", Pattern.CASE_INSENSITIVE); Matcher matcher = pattern.matcher(EXAMPLE_TEST); // check all occurance while (matcher.find()) { System.out.print("Start index: " + matcher.start()); System.out.print(" End index: " + matcher.end() + " "); System.out.println(matcher.group()); } // now create a new pattern and matcher to replace whitespace with tabs Pattern replace = Pattern.compile("\\s+"); Matcher matcher2 = replace.matcher(EXAMPLE_TEST); System.out.println(matcher2.replaceAll("\t")); } }
6、java正则表达式的例子
下面列出了正则表达式的典型例子6.1、|
任务:写一个可以匹配包含Joe或Jim,或者同时包含两者的正则表达式。package de.vogella.regex.eitheror; import org.junit.Test; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; public class EitherOrCheck { @Test public void testSimpleTrue() { String s = "humbapumpa jim"; assertTrue(s.matches(".*(jim|joe).*")); s = "humbapumpa jom"; assertFalse(s.matches(".*(jim|joe).*")); s = "humbaPumpa joe"; assertTrue(s.matches(".*(jim|joe).*")); s = "humbapumpa joe jim"; assertTrue(s.matches(".*(jim|joe).*")); } }
6.2、电话号码(欧美)
任务:写一个可以匹配电话号码的正则表达式。package de.vogella.regex.phonenumber; import org.junit.Test; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; public class CheckPhone { @Test public void testSimpleTrue() { String pattern = "\\d\\d\\d([,\\s])?\\d\\d\\d\\d"; String s= "1233323322"; assertFalse(s.matches(pattern)); s = "1233323"; assertTrue(s.matches(pattern)); s = "123 3323"; assertTrue(s.matches(pattern)); } }
6.3、检查数量范围
任务:检查包含3位数字的文本。package de.vogella.regex.numbermatch; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.junit.Test; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; public class CheckNumber { @Test public void testSimpleTrue() { String s= "1233"; assertTrue(test(s)); s= "0"; assertFalse(test(s)); s = "29 Kasdkf 2300 Kdsdf"; assertTrue(test(s)); s = "99900234"; assertTrue(test(s)); } public static boolean test (String s){ Pattern pattern = Pattern.compile("\\d{3}"); Matcher matcher = pattern.matcher(s); if (matcher.find()){ return true; } return false; } }
6.4、链接检查
任务:提取网页中的链接。package de.vogella.regex.weblinks; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; public class LinkGetter { private Pattern htmltag; private Pattern link; public LinkGetter() { htmltag = Pattern.compile("<a\\b[^>]*href=\"[^>]*>(.*?)</a>"); link = Pattern.compile("href=\"[^>]*\">"); } public List<String> getLinks(String url) { List<String> links = new ArrayList<String>(); try { BufferedReader bufferedReader = new BufferedReader( new InputStreamReader(new URL(url).openStream())); String s; StringBuilder builder = new StringBuilder(); while ((s = bufferedReader.readLine()) != null) { builder.append(s); } Matcher tagmatch = htmltag.matcher(builder.toString()); while (tagmatch.find()) { Matcher matcher = link.matcher(tagmatch.group()); matcher.find(); String link = matcher.group().replaceFirst("href=\"", "") .replaceFirst("\">", "") .replaceFirst("\"[\\s]?target=\"[a-zA-Z_0-9]*", ""); if (valid(link)) { links.add(makeAbsolute(url, link)); } } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return links; } private boolean valid(String s) { if (s.matches("javascript:.*|mailto:.*")) { return false; } return true; } private String makeAbsolute(String url, String link) { if (link.matches("http://.*")) { return link; } if (link.matches("/.*") && url.matches(".*$[^/]")) { return url + "/" + link; } if (link.matches("[^/].*") && url.matches(".*[^/]")) { return url + "/" + link; } if (link.matches("/.*") && url.matches(".*[/]")) { return url + link; } if (link.matches("/.*") && url.matches(".*[^/]")) { return url + link; } throw new RuntimeException("Cannot make the link absolute. Url: " + url + " Link " + link); } }
6.5、检查重复的单词
下面的正则表达式可以匹配重复的单词:\b(\w+)\s+\1\b
\b表示词边界,而\1表示第一组匹配到的内容。
(?!-in)\b(\w+) \1\b 匹配不以-in开头的重复单词。
提示:可以添加(?s)进行多行匹配。
6.6、匹配以新的一行开始的元素
(\n\s*)title
6.7、查找Non-Javadoc语句
(?s) /\* \(non-Javadoc\).*?\*/
6.7.1、Replacing the DocBook table statement with Asciidoc
你可以替换像下面这样的语句<programlisting language="java"> <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" href="./examples/statements/MyClass.java" /> </programlisting>
对应的正则表达式
`\s+<programlisting language="java">\R.\s+<xi:include xmlns:xi="http://www\.w3\.org/2001/XInclude" parse="text" href="\./examples/(.*).\s+/>\R.\s+</programlisting>`
目标可以是你的例子
`\R[source,java]\R----\R include::res/$1[]\R----
相关文章推荐
- java实现一个抽奖概率类
- Java中在特定区间产生随机数
- 关于java反射机制复习的那些事
- Retrofit+Rxjava服务器IP轮询重试机制实现
- spring mvc 使用小心得
- crc16 ccitt 单片机与java匹配算法
- JAVA hashmap知识整理
- JavaWeb 之 Cookie详解
- java中的mvc和三层结构究竟是什么关系
- 构建Maven+SpringMVC的Web工程(上)
- JavaWeb学习总结(十五)--过滤器的应用
- eclipse查看jar包源代码乱码问题解决
- Spring mvc 原理浅析
- [置顶] java书单
- 华为上机试题(java)找出一个字符串中出现次数最多的字符
- SpringMVC 各类 视图解析器分析
- JDK AIO编程
- 如何将java工程转变为web工程
- RxJava
- Swing开发之JProgressBar篇