java正则表达式教程(翻译)

来源:互联网 发布:anaconda与python版本 编辑:程序博客网 时间:2024/06/03 18:24
翻译至:http://www.vogella.com/tutorials/JavaRegularExpressions/article.html

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 elementsString 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 14for (String string : splitString) {System.out.println(string);}// replace all whitespace with tabsSystem.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----

1 0
原创粉丝点击