TA的每日心情 | 开心 2021-3-12 23:18 |
---|
签到天数: 2 天 [LV.1]初来乍到
|
- -、分组提取
- 以apache log为例,如下:
- 192.168.1.138 - - [03/Feb/2006:01:40:20 +0800] "GET /phpinfo.php HTTP/1.1" 404 295
- //分别为 客户端IP、访问日期、请求路径、服务端响应Code、请求文件大小
复制代码 其正则表达式为:
String pattern=
"^([\d.]+)(\S+)(\S+)\[([\w:/]+\s[+|-]\d{4})\]\s"(.+)"\s(\d{3})\s(\d+)"; 想到上面正则中括号()的作用了么?可以通过group(i)快速的将每组()中内容提取出来。 第一组([d.]+):将IP地址匹配出来 第四组([w:/]+s[+|-]d{4}):将时间匹配出来 第五组(.+):将客户端请求内容匹配出来 第六组(d{3}):将服务端响应Code匹配出来 第七组(d+):将文件大小匹配出来
- 测试程序:
- import java.util.regex.*;
- public class Test {
- public static void main(String[] args) {
- String pattern="^([\d.]+)(\S+)(\S+)\[([\w:/]+\s[+|-]\d{4})\]\s"(.+)"\s(\d{3})\s(\d+)";
- String log="192.168.1.138--[03/Feb/2006:01:40:20 +0800] "Get /phpinfo.php HTTP/1.1" 404 295";
-
- System.out.println("pattern: " + pattern);
- System.out.println("log: " + log);
-
- Pattern p = Pattern.compile(pattern);
- Matcher m = p.matcher(log);
-
- if (m.find()) {
- System.out.println("IP Address: " + m.group(1));
- System.out.println("Date&Time: " + m.group(4));
- System.out.println("Request: " + m.group(5));
- System.out.println("Response: " + m.group(6));
- System.out.println("Size: " + m.group(7));
- } else {
- System.out.println("error!");
- }
- }
-
- }
-
-
- 程序输出:
-
- C:java>java Test
- pattern: ^([d.]+)(S+)(S+)[([w:/]+s[+|-]d{4})]s"(.+)"s(d{3})s(d+)
- log: 192.168.1.138--[03/Feb/2006:01:40:20 +0800] "Get /phpinfo.php HTTP/1.1" 404 295
- IP Address: 192.168.1.138
- Date&Time: 03/Feb/2006:01:40:20 +0800
- Request: Get /phpinfo.php HTTP/1.1
- Response: 404
- Size: 295
- 二、替换匹配的字符串
- 假如需要替换掉匹配正则表达式的字符串,我们可以自已使用String类的subString()方法,
- 但jdk1.4的正则表达式API中提供了实现此功能的相关方法,如下:
- * replaceAll(newString); 替换全部符合正则表达式的子串为newString.
- * appendReplacement(StringBuffer, newString); 将字符串中匹配正则的
- 子串之前的字符串先传入到StringBuffer中,然后再加上newString。
- * appendTail(StringBuffer); 将字符串中匹配最后一个正则表达式后面的
- 字符串传入到StringBuffer(通常和appendReplacement一起使用).
- 看下面的例子:
-
- import java.util.regex.*;
- public class Test{
- public static void main(String[] args) {
- // 匹配d开头,接着是a或e最少一次,最多2次,再接着是mon
- // 感觉自已跟唐僧一样,N�嗦 -__-!!
-
- String pattern ="d[ae]{1,2}mon";
- String input ="Unix hath demons and deamons in it!";
- System.out.println("Input:" + input);
-
- Pattern p = Pattern.compile(pattern);
- Matcher m = p.matcher(input);
- // 两个子串符合: demons, deamons.
- System.out.println("ReplaceAll:A=" + m.replaceAll("A"));
-
- m.reset();
-
- StringBuffer sb = new StringBuffer();
- System.out.println("Append methods:");
-
- while (m.find()) {
- m.appendReplacement(sb,"B");
- System.out.println(sb);
- }
-
- m.appendTail(sb);
- System.out.println(sb.toString());
- }
- }
- 运行结果:
- C:java>java Test
- Input:Unix hath demons and deamons in it!
- ReplaceAll:A=Unix hath As and As in it!
- Append methods:
- Unix hath B
- Unix hath Bs and B
- Unix hath Bs and Bs in it!
- 三、查找
- 有时候你需要把字符串中匹配正则表达式的那一段找出来,接着前一个例子,
- 你可以调用“查找”方法成功后,调用下面的方法将匹配的字符串找出来。
- start(), end() 返回字符串中匹配正则表达式的子串的开始位置和结束位置
- groupCount() 返回()号匹配的数目,如果有的话。返回0表示没有使用()组,下面将会有介绍
- group(int i) 返回正则表达式()匹配的第i组,如果i小于或等于groupCount()则返回相应的()匹配值,
- 如果调用group(0)或group()则返回整个匹配正则表达式的部分
- 下面这个例子使用group()直接将整个匹配正则表达式的子字符串取出来:
- import java.util.regex.*;
- public class Test2{
-
- public static void main(String[] args) {
- // 匹配Q开头,第二个字符不为u,后面接数字1次或多次,后面再.号
- String pattern ="Q[^u]\d+\.";
- Pattern p = Pattern.compile(pattern);
-
- String line ="Order QT300. Now !";
-
- Matcher m = p.matcher(line);
- if (m.find()) {
- // m.group()须调用相关查找方法成功后才能调用
- System.out.println(pattern + " matches "" + m.group() +"" in "" + line +""");
- } else {
- System.out.println("NO MATCH");
- }
- }
- }
-
- // 输出:Q[^u]d+. matches "QT300." in "Order QT300. Now !"
-
- 上面这个例子也可以使用start(), end()方法来完成:
- import java.util.regex.*;
- public class Test3{
-
- public static void main(String[] args) {
- String pattern = "Q[^u]\d+\.";
- Pattern p = Pattern.compile(pattern);
-
- String line = "Order QT300. Now!";
- Matcher m = p.matcher(line);
-
- if (m.find()) {
- System.out.println(pattern + " matches ""
- + line.substring(m.start(), m.end()) + "" in "" + line
- + """);
- } else {
- System.out.println("NO MATCH!");
- }
- }
- }
- // 输出:Q[^u]d+. matches "QT300." in "Order QT300. Now !"
- 四、转换
- 假设你想将字符串:
- Smith, John
- 通过正则转换为:
- John Smith
- 可以这样做:
- import java.util.regex.*;
- public class Test4{
-
- public static void main(String[] args) {
-
- String line = "Smith, John";
- // 这就是上面所说的()号,如果调用groupCount()的话,将输出2
- // 匹配任何字符0次或多次,然后是","号和空格,再匹配任何字符0次和多次
- // 上面的任何字符不包括换行符
- Pattern p = Pattern.compile("(.*), (.*)");
-
- Matcher m = p.matcher(line);
- if (m.find()) {
- // 先取上面正则()中匹配的group 2,也就是John
- // 然后再取()中匹配的group 1,也就是Smith
- System.out.println(m.group(2) + " " + m.group(1));
- } else {
- System.out.println("NO MATCH!");
- }
- }
- }
- // 输出: John Smith
-
- 再看一个例子:交换两个参数的位置
- import java.util.regex.Pattern;
- import java.util.regex.Matcher;
- public class RearrangeText {
- public static void main(String args[]) {
- String regEx = "(Math.pow)"+ // Math.pow
- "\s*\(" + // Opening parenthesis
- "\s*([+|-]?(\d+\.?\d*|\.\d+)|([a-zA-Z]\w*))" + // First argument
- "\s*,\s*" + // Comma
- "([+|-]?(\d+\.?\d*|\.\d+)|([a-zA-Z]\w*))" + // Second argument
- "\s*\)"; // Closing parenthesis
- String oldCode = "double result = Math.pow( 3.0, 16.0); " +
- "
- double resultSquared = Math.pow(2 ,result );"+
- "
- double hypotenuse = Math.sqrt(Math.pow(2.0, 30.0)+Math.pow(2 , 40.0));";
- Pattern pattern = Pattern.compile(regEx);
- Matcher m = pattern.matcher(oldCode);
- StringBuffer newCode = new StringBuffer();
- while(m.find()) {
- m.appendReplacement(newCode, "$1\($5,$2\)");//$1表示第一组,$i表示第i组
- //System.out.println("OK="+newCode);
- }
- m.appendTail(newCode);
- System.out.println("Original Code:
- "+oldCode.toString());
- System.out.println("
- New Code:
- "+newCode.toString());
- }
- }
- 运行结果:
- C:java>java RearrangeText
- Original Code:
- double result = Math.pow( 3.0, 16.0);
- double resultSquared = Math.pow(2 ,result );
- double hypotenuse = Math.sqrt(Math.pow(2.0, 30.0)+Math.pow(2 , 40.0));
- New Code:
- double result = Math.pow(16.0,3.0);
- double resultSquared = Math.pow(result,2);
- double hypotenuse = Math.sqrt(Math.pow(30.0,2.0)+Math.pow(40.0,2));
- 五、匹配
- 在java中我们可以简单的使用String类的matches()方法来判断当前字符串是否符合
- 你所给定的正则表达式模式。matches()方法接受正则表达式做为参数,返回boolean类型。
- if (inputString.matches(regexPattern)) {
- // 字符串inputString匹配regexPattern这个模式
- }
- 代码很简单,但是效率不高,如果在程序中使用不止一次,我们可以使用Pattern和Matcher,例子见下:
- import java.util.regex.*;
- public class Test5{
-
- public static void main(String[] args) throws PatternSyntaxException {
- String pattern = "^Q[^u]\d+\.";
- String input = "Qa777. is the next flight. It is on time.";
-
- Pattern p = Pattern.compile(pattern);
- boolean found = p.matcher(input).lookingAt();
-
- System.out.println(""" + pattern + """
- + (found ? " matches "" : " doesn"t match "") + input + """);
- }
- }
- 运行结果
- C:java>java Test5
- "^Q[^u]d+." matches "Qa777. is the next flight. It is on time."
- 六、小结:
- 在程序中使用正则表达式的步骤一般如下:
- 1. 建立Pattern对象,通过静态方法Pattern.compile();
- 2. 取得Matcher对象,通过pattern.matcher(CharSequence charSequence);
- 3. 调用Matcher对象的相关查找方法。
- java.lang.CharSequence接口是在JDK1.4版本中被添加进来的,它为不同种类的char序列
- 提供了统一的只读访问。实现的类有String, StringBuffer, java.nio.CharBuffer
- Matcher提供几个不同的查找方法,比String类的matches()方法更灵活,如下:
- match() 使用整个字符串与相关模式相比较,和String的matches()差不多
- lookingAt() 从字符串开头的地方与相关模式比较
- find() 匹配字符串,没有必要从字符串的第一个字符开始,如果前一个操作匹配,
- 而且匹配器没有重置的话,则从不匹配的第一个字符开始。
- 上面每个方法都返回boolean类型,返回true则意味的匹配,返回false则不匹配。
- 要检测给定的String是否匹配给定的模式,只须下面这样就可以了:
- Matcher m = Pattern.compile(yourPattern).matcher(yourString);
-
- if (m.find()) {
- System.out.println(“match”);
- } else {
- System.out.println(“no match”);
- }
复制代码
源码下载:http://file.javaxxz.com/2014/11/1/000124421.zip |
|