Java正则表达式基础知识及实例说明

众所周知,在程序开发中,难免会遇到需要匹配、查找、替换、判断字符串的情况发生,而这些情况有时又比较复杂,如果用纯编码方式解决,往往会浪费程序员的时间及精力。因此,学习及使用正则表达式,便成了解决这一矛盾的主要手段。
 大 家都知道,正则表达式是一种可以用于模式匹配和替换的规范,一个正则表达式就是由普通的字符(例如字符a到z)以及特殊字符(元字符)组成的文字模式,它 用以描述在查找文字主体时待匹配的一个或多个字符串。正则表达式作为一个模板,将某个字符模式与所搜索的字符串进行匹配。
  自从jdk1.4推出java.util.regex包,就为我们提供了很好的JAVA正则表达式应用平台。
 
 因为正则表达式是一个很庞杂的体系,所以我仅例举些入门的概念,更多的请参阅相关书籍及自行摸索。 

// 反斜杠
/t 间隔 ('/u0009')
/n 换行 ('/u000A')
/r 回车 ('/u000D')
/d 数字 等价于[0-9]
/D 非数字 等价于[^0-9]
/s 空白符号 [/t/n/x0B/f/r]
/S 非空白符号 [^/t/n/x0B/f/r]
/w 单独字符 [a-zA-Z_0-9]
/W 非单独字符 [^a-zA-Z_0-9]
/f 换页符
/e Escape
/b 一个单词的边界
/B 一个非单词的边界
/G 前一个匹配的结束

^为限制开头
^java     条件限制为以Java为开头字符
$为限制结尾
java$     条件限制为以java为结尾字符
.  条件限制除/n以外任意一个单独字符
java..     条件限制为java后除换行外任意两个字符


加入特定限制条件「[]」
[a-z]     条件限制在小写a to z范围中一个字符
[A-Z]     条件限制在大写A to Z范围中一个字符
[a-zA-Z] 条件限制在小写a to z或大写A to Z范围中一个字符
[0-9]     条件限制在小写0 to 9范围中一个字符
[0-9a-z] 条件限制在小写0 to 9或a to z范围中一个字符
[0-9[a-z]] 条件限制在小写0 to 9或a to z范围中一个字符(交集)

[]中加入^后加再次限制条件「[^]」
[^a-z]     条件限制在非小写a to z范围中一个字符
[^A-Z]     条件限制在非大写A to Z范围中一个字符
[^a-zA-Z] 条件限制在非小写a to z或大写A to Z范围中一个字符
[^0-9]     条件限制在非小写0 to 9范围中一个字符
[^0-9a-z] 条件限制在非小写0 to 9或a to z范围中一个字符
[^0-9[a-z]] 条件限制在非小写0 to 9或a to z范围中一个字符(交集)

在限制条件为特定字符出现0次以上时,可以使用「*」
J*     0个以上J
.*     0个以上任意字符
J.*D     J与D之间0个以上任意字符

在限制条件为特定字符出现1次以上时,可以使用「+」
J+     1个以上J
.+     1个以上任意字符
J.+D     J与D之间1个以上任意字符

在限制条件为特定字符出现有0或1次以上时,可以使用「?」
JA?     J或者JA出现

限制为连续出现指定次数字符「{a}」
J{2}     JJ
J{3}     JJJ
文字a个以上,并且「{a,}」
J{3,}     JJJ,JJJJ,JJJJJ,???(3次以上J并存)
文字个以上,b个以下「{a,b}」
J{3,5}     JJJ或JJJJ或JJJJJ
两者取一「|」
J|A     J或A
Java|Hello     Java或Hello
 
「()」中规定一个组合类型
比如,我查询<a href=/"index.html/">index</a>中<a href></a>间的数据,可写作<a.*href=/".*/">(.+?)</a>

在使用Pattern.compile函数时,可以加入控制正则表达式的匹配行为的参数:
Pattern Pattern.compile(String regex, int flag)
 
Java代码 
  1. public class RegexHarnessTest   
  2. {  
  3.     public static void main(String args[])  
  4.     {  
  5.         String[] regex = {"([\u4E00-\u9FA5]+,?)+",  
  6.                 "\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}",  
  7.                 "\\d{4}[A-Z]{2}",  
  8.                 "[0-9]{1.3}"};  
  9.         String[] input = {"开发高手,程序员的朋友,开发者的助手",  
  10.                 "IP:71.42.164.8,192.168.1.1,7.78.3.221",  
  11.                 "美国汽车牌照:3456MW,12345M,6789NY",  
  12.                 "数字:345,678"};  
  13.         RegexHarness rh = new RegexHarness();  
  14.         for(int i=0;i<regex.length;i++)  
  15.         {  
  16.             rh.setRegex(regex[i]);  
  17.             rh.setInput(input[i]);  
  18.             if(rh.initialize())  
  19.             {  
  20.                 System.out.println("\n-----匹配方式:全文匹配,方法:matches调用开始-----\n");  
  21.                 rh.validateEntireText();  
  22.                 System.out.println(rh.getResults());  
  23.                 System.out.println("\n-----匹配方式:全文匹配,方法:matches调用结束-----\n");  
  24.                 System.out.println("\n-----匹配方式:部分匹配,方法:find调用开始-----\n");  
  25.                 rh.validatePartText();  
  26.                 System.out.println(rh.getResults());  
  27.                 System.out.println("\n-----匹配方式:部分匹配,方法:find调用结束-----\n");  
  28.             }  
  29.             else  
  30.             {  
  31.                 System.out.println(rh.getRegexError());  
  32.             }  
  33.         }  
  34.           
  35.         System.exit(0);  
  36.     }  
  37. }  

 

Java代码 
  1. import java.util.regex.Matcher;  
  2. import java.util.regex.Pattern;  
  3. import java.util.regex.PatternSyntaxException;  
  4.   
  5. public class RegexHarness   
  6. {  
  7.     /**regex表示正则表达式,input表示要匹配或验证的文本或字符串*/  
  8.     private String regex="",input="";  
  9.     /**regexError表示当正则表达式出现语法错误时,相关的错误信息 
  10.      * results表示匹配后的结果*/  
  11.     private String regexError="",results="";  
  12.     private Pattern pattern;  
  13.     private Matcher matcher;  
  14.       
  15.     public RegexHarness()  
  16.     {  
  17.         this("","");  
  18.     }  
  19.       
  20.     public RegexHarness(String regex,String input)  
  21.     {  
  22.         setRegex(regex);  
  23.         setInput(input);  
  24.     }  
  25.       
  26.     /** 
  27.      * 初始化 
  28.      * @return 
  29.      */  
  30.     public boolean initialize()  
  31.     {  
  32.         try  
  33.         {  
  34.             /* 
  35.              * 使用Pattern类的静态compile方法,接收一个代表正则 
  36.              * 表达式的字符串(变量:regex)的参数,并返回一个指定的 
  37.              * 正则表达式的Pattern对象的pattern 
  38.              */  
  39.             pattern = Pattern.compile(regex);  
  40.             /* 
  41.              * 利用刚刚返回的Pattern类的实例pattern,并调用pattern 
  42.              * 的matcher方法。该方法接收一个用于匹配的实现了CharSequence 
  43.              * 接口的对象input,并将返回一个Matcher对象赋值给变量matcher。 
  44.              */  
  45.             matcher = pattern.matcher(input);  
  46.             return true;  
  47.         }  
  48.         catch (PatternSyntaxException pse) {  
  49.             regexError = "\n正则表达式语法错误!错误的相关信息如下:" +  
  50.             "\n当前的正则表达式是:" + pse.getPattern() +  
  51.             "\n错误描述:" + pse.getDescription() +   
  52.             "\n错误信息:" + pse.getMessage() +  
  53.             "\n错误索引:" + pse.getIndex();  
  54.             return false;  
  55.         }  
  56.     }  
  57.       
  58.     /** 
  59.      * 根据正则表达式来匹配输入的整个文本,并得到匹配结果<br> 
  60.      * 本方法不返回任何数据,先调用matcher的方法matches, 
  61.      * matches方法根据给定的正则表达式来匹配的整个文本。 
  62.      * 如果整个文本都匹配给定的正则表达式,就调用matcher的 
  63.      * group方法,该方法返回与查找模式相匹配的查找对象的字符 
  64.      * 串,并将得到的匹配文本再赋值给字符串变量results,返回 
  65.      * 真值。 
  66.      */  
  67.     public void validateEntireText()  
  68.     {  
  69.         boolean findMathText = false;  
  70.         results = "当前的正则表达式是:" + regex +  
  71.         "\n当前匹配的文本是:" + input + "\n\n";  
  72.         if(matcher.matches())  
  73.         {  
  74.             results += "找到全文匹配的文本\"" + matcher.group() + "\"。\n";  
  75.             findMathText = true;  
  76.         }  
  77.         if(!findMathText)  
  78.         {  
  79.             results += "没有发现全文匹配的文本。\n";  
  80.         }  
  81.     }  
  82.       
  83.     /** 
  84.      * 根据正则表达式来匹配输入的部分文本,并得到匹配结果<br> 
  85.      * 本方法不返回任何数据,但是调用的是matcher的方法find, 
  86.      * find方法根据给定的正则表达式来匹配的文本中的子字符串。 
  87.      * 和matches方法不同之处在于,只有被匹配的文本中的部分内容 
  88.      * 符合给定的正则表达式时,find方法才返回真值。 
  89.      */  
  90.     public void validatePartText()  
  91.     {  
  92.         boolean findMathText = false;  
  93.         results = "当前的正则表达式是:" + regex +  
  94.         "\n当前匹配的文本是:" + input + "\n\n";  
  95.         while(matcher.find())  
  96.         {  
  97.             results += "找到部分匹配的文本\"" + matcher.group()+  
  98.             "\"\t起始索引:" + matcher.start() +  
  99.             "\t结束索引:" + matcher.end() + "。\n";  
  100.             findMathText = true;  
  101.         }  
  102.         if(!findMathText)  
  103.         {  
  104.             results += "没有发现部分匹配的文本。\n";  
  105.         }  
  106.     }  
  107.       
  108.     public String getResults()  
  109.     {  
  110.         return this.results;  
  111.     }  
  112.       
  113.     public String getRegexError()  
  114.     {  
  115.         return this.regexError;  
  116.     }  
  117.       
  118.     public void setRegex(String regex)  
  119.     {  
  120.         this.regex = regex;  
  121.     }  
  122.       
  123.     public void setInput(String input)  
  124.     {  
  125.         this.input = input;  
  126.     }  
  127. }  

 

Java代码 
  1. import javax.swing.JOptionPane;  
  2.   
  3. public class RegexStringReplace   
  4. {  
  5.     public static void main(String args[])  
  6.     {  
  7.         String originalString = "This is 哈哈 JAVA code* * * * *";  
  8.         String output = "原始字符串:"+ originalString;  
  9.         //替换'*' 为 '^'  
  10.         originalString = originalString.replaceAll("\\*", "^ ");  
  11.         output+="\n*被替换成^ 后的字符串:"+originalString;  
  12.           
  13.         //替换'哈哈'为'HaHa's'  
  14.         originalString = originalString.replaceAll("哈哈", "HaHa's");  
  15.         output+="\n\"哈哈\"替换成\"HaHa's\":"+originalString;  
  16.           
  17.         //将字符串中的每个单词都替换成"word"  
  18.         output+="\n每个单词都替换成\"word\":"+originalString.replaceAll("\\w+", "word");  
  19.           
  20.         JOptionPane.showMessageDialog(null, output,"Java正则表达式例子",JOptionPane.INFORMATION_MESSAGE);  
  21.         System.exit(0);  
  22.     }  
  23. }  

 

Java代码 
  1. import javax.swing.JOptionPane;  
  2.   
  3. public class RegexStringReplaceFirstAndSplit  
  4. {  
  5.     public static void main(String args[])  
  6.     {  
  7.         String originalString="1, one, 2, two, 3, three, 4, four, 5, five";  
  8.         String output = "原始字符串:\n" + originalString;  
  9.         //迭代3次,将字符串中第一次出现的数字替换成字符串'dight'  
  10.         for(int i=0;i<3;i++)  
  11.         {  
  12.             originalString = originalString.replaceFirst("\\d", "digit");  
  13.         }  
  14.         output += "\n头三个数字被替换成\"digit\"后的字符串:\n" + originalString;  
  15.         //分隔出现逗号的子字符串,逗号后面可以匹配任意的空白字符  
  16.         String[] result = originalString.split(",\\s*");  
  17.         output +="\n字符串依据逗号来分割后的结果";  
  18.         for(int i=0;i<result.length;i++)  
  19.         {  
  20.             output+="\n"+result[i];  
  21.         }  
  22.         JOptionPane.showMessageDialog(null, output,"java正则表达式",JOptionPane.INFORMATION_MESSAGE);  
  23.         System.exit(0);  
  24.     }  
  25. }  

 

Java代码 
  1. import java.awt.Container;  
  2. import java.awt.Font;  
  3. import java.awt.GridLayout;  
  4. import java.awt.event.ActionEvent;  
  5. import java.awt.event.ActionListener;  
  6.   
  7. import javax.swing.JButton;  
  8. import javax.swing.JFrame;  
  9. import javax.swing.JLabel;  
  10. import javax.swing.JOptionPane;  
  11. import javax.swing.JPanel;  
  12. import javax.swing.JTextField;  
  13.   
  14. public class RegexStringTest extends JFrame  
  15. {  
  16.     private static final long serialVersionUID = -1564020173888781534L;  
  17.     private JTextField phoneTextField;  
  18.     private JTextField zipTextField;  
  19.     private JTextField addressTextField;  
  20.     private JTextField firstTextField;  
  21.     private JTextField lastTextField;  
  22.     private JTextField chineseTextField;  
  23.       
  24.     private Font songTi = new Font("宋体",Font.PLAIN,12);  
  25.     public RegexStringTest()  
  26.     {  
  27.         super("基于字符串的正则表达式");  
  28.         //创建图形界面  
  29.         JLabel phoneLabel = new JLabel("电话");  
  30.         phoneLabel.setFont(songTi);  
  31.         JLabel zipLabel = new JLabel("邮政编码");  
  32.         zipLabel.setFont(songTi);  
  33.         JLabel addressLabel = new JLabel("通信地址");  
  34.         addressLabel.setFont(songTi);  
  35.         JLabel firstLabel = new JLabel("First Name:(英文,第一个字母必须大写)");  
  36.         firstLabel.setFont(songTi);  
  37.         JLabel lastLabel = new JLabel("Last Name:(英文,第一个字母必须大写)");  
  38.         lastLabel.setFont(songTi);  
  39.         JLabel chineseLabel = new JLabel("中文");  
  40.         chineseLabel.setFont(songTi);  
  41.         JButton okButton =  new JButton("验证");  
  42.         okButton.setFont(songTi);  
  43.         okButton.addActionListener(new ActionListener()  
  44.         {  
  45.             //内部类开始  
  46.             public void actionPerformed(ActionEvent e) {  
  47.                 validateDate();  
  48.             }//内部类结束  
  49.         });//调用addActionListener结束  
  50.           
  51.         phoneTextField = new JTextField(15);  
  52.         zipTextField = new JTextField(6);  
  53.         addressTextField = new JTextField(35);  
  54.         firstTextField = new JTextField(20);  
  55.         lastTextField = new JTextField(20);  
  56.         chineseTextField = new JTextField(30);  
  57.           
  58.         JPanel firstName = new JPanel();  
  59.         firstName.add(firstLabel);  
  60.         firstName.add(firstTextField);  
  61.           
  62.         JPanel lastName = new JPanel();  
  63.         lastName.add(lastLabel);  
  64.         lastName.add(lastTextField);  
  65.           
  66.         JPanel address = new JPanel();  
  67.         address.add(addressLabel);  
  68.         address.add(addressTextField);  
  69.           
  70.         JPanel zipAndPhone = new JPanel();  
  71.         zipAndPhone.add(zipLabel);  
  72.         zipAndPhone.add(zipTextField);  
  73.         zipAndPhone.add(phoneLabel);  
  74.         zipAndPhone.add(phoneTextField);  
  75.           
  76.         JPanel chinese = new JPanel();  
  77.         chinese.add(chineseLabel);  
  78.         chinese.add(chineseTextField);  
  79.           
  80.         JPanel ok = new JPanel();  
  81.         ok.add(okButton);  
  82.           
  83.         //把GUI部件添加在容器中  
  84.         Container container = getContentPane();  
  85.         container.setLayout(new GridLayout(6,1));  
  86.         container.add(firstName);  
  87.         container.add(lastName);  
  88.         container.add(address);  
  89.         container.add(zipAndPhone);  
  90.         container.add(chinese);  
  91.         container.add(ok);  
  92.           
  93.         pack();  
  94.         setVisible(true);  
  95.     }//RegexStringTest构造器结束  
  96.       
  97.     public static void main(String args[])  
  98.     {  
  99.         RegexStringTest application = new RegexStringTest();  
  100.         application.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  
  101.     }  
  102.       
  103.     /** 
  104.      * 处理鼠标点击事件 
  105.      */  
  106.     private void validateDate()  
  107.     {  
  108.         //确保每个文本框不为空  
  109.         if(lastTextField.getText().equals("") ||  
  110.                 firstTextField.getText().equals("")||  
  111.                 addressTextField.getText().equals("")||  
  112.                 zipTextField.getText().equals("")||  
  113.                 phoneTextField.getText().equals("")||  
  114.                 chineseTextField.getText().equals(""))  
  115.         {  
  116.             JOptionPane.showMessageDialog(this, "每个栏目都必须填写");  
  117.         }  
  118.         else if(!firstTextField.getText().matches("[A-Z][a-zA-Z]*"))  
  119.         {//验证First Name是不是以大写字母的一个英文单词  
  120.             /* 
  121.              * [A-Z]匹配单个大写字母,其后面的[a-zA-Z]*表示可以匹配任意数目的 
  122.              * 字母。通常,在正则表达式中出现运算符(量词)"*"的时候,程序将匹配 
  123.              * "*"前的0个或多个子表达式。同理,"A*"和"A+"都与"A"匹配,但"A*" 
  124.              * 还可以匹配一个空的字符串。 
  125.              */  
  126.             JOptionPane.showMessageDialog(this, "First Name非法");  
  127.         }  
  128.         else if(!lastTextField.getText().matches("[A-Z][a-zA-Z]*"))  
  129.         {//验证Last Name是不是以大写字母开头的一个英文单词  
  130.             JOptionPane.showMessageDialog(this, "Last Name非法");  
  131.         }  
  132.         else if(!addressTextField.getText().matches("\\d+\\s+([a-zA-Z]+|[a-zA-Z]+\\s[a-zA-Z]+)"))  
  133.         {//验证地址是否为数字开始,并包含一个单词或者两个单词  
  134.             /* 
  135.              * 这里的地址格式是西方的格式,也就是门牌号在前,街名在后。 
  136.              * \\d+\\s+([a-zA-Z]+|[a-zA-Z]+\\s[a-zA-Z]+) 
  137.              * 首先是匹配任意的数字(\\d+),"\d"是表示数字字符,这里之所以要加上一个"\" 
  138.              * 是因为"\"在Java中是作用转义字符的。所以这里的"\\d"就正好表示正则表达 
  139.              * 式中的"\d"。然后,继续验证数字后面是否至少有一个空白字符(\\s+)。字符 
  140.              * "|"将表达式与其左边或者右边的字符串相匹配。如:Hello(Tom|Rich)就和 
  141.              * Hello Tom以及Hello Rich相匹配。括号用于将正则表达式的各个部分连接 
  142.              * 起来。这里字符"|"左边([a-zA-Z]+)匹配一个单词,而右边 
  143.              * ([a-zA-Z]+\\s[a-zA-Z]+)匹配两个单词,注意两个单词之间只能有一个空白 
  144.              * 字符(\\s)。因此,这里如果用户输入"123 Main"或者"123 Main Street" 
  145.              * 都是有效的。 
  146.              */  
  147.             JOptionPane.showMessageDialog(this, "地址非法");  
  148.         }  
  149.         else if(!zipTextField.getText().matches("\\d{5}"))  
  150.         {//验证邮政编码是否为一个5位数的数字  
  151.             /* 
  152.              * "\\d{5}"表明邮政编码匹配5个数字。另外可以用其他写法实现相同的功能 
  153.              * 如:"[0-9]{5}" 
  154.              */  
  155.             JOptionPane.showMessageDialog(this, "邮政编码非法");  
  156.         }  
  157.         else if(!phoneTextField.getText().matches("[1-9]\\d{2}-[1-9]\\d{2}-\\d{4}"))  
  158.         {//验证电话号码格式是否为123-456-7890并且区号和电话号码的第一位不能是数字0  
  159.             /* 
  160.              * [1-9]\\d{2}-[1-9]\\d{2}-\\d{4} 
  161.              * 本例采用的美国的电话号码形式,如123-456-7890,即头三位数字为区号 
  162.              * ,之后紧跟一个短横线,接着是电话号码的头三位,之后又是一个短横线, 
  163.              * 最后是电话号码的最后四位数。注意这里"[1-9]\\d{2}"表示匹配一个3位 
  164.              * 数的数字,但其第一个数字不能为0.如果希望123-4567890这种格式的电话 
  165.              * 号码也合法,可以修改"[1-9]\\d{2}-[1-9]\\d{2}-?\\d{4}" 
  166.              * 我们在第2个短横线后加一个"?"号,表示"-"可以出现,也可以不出现。 
  167.              */  
  168.             JOptionPane.showMessageDialog(this, "非法的电话号码");  
  169.         }  
  170.         else if(!chineseTextField.getText().matches("[\u4E00-\u9FA5]+"))  
  171.         {  
  172.             /* 
  173.              * [\u4E00-\u9FA5]+,验证了用户输入的数据是否全部为中文字符。 
  174.              */  
  175.             JOptionPane.showMessageDialog(this, "只能输入中文");  
  176.         }  
  177.         else  
  178.         {  
  179.             JOptionPane.showMessageDialog(this, "谢谢,您输入的完全合法");  
  180.         }  
  181.     }  
  182. } 
posted @ 2015-09-18 09:29  wzhanke  阅读(345)  评论(0编辑  收藏  举报