处理捕获组的方法
应用程序源代码RegexDemo
包括方法调用m.group()
。该方法是该类旨在处理捕获组 group()
的几种方法之一:Matcher
-
该方法
int groupCount()
返回解析器模式中捕获的组的数量。该数字不考虑特殊捕获组编号 0,它对应于整个模式。 -
该方法
String group()
返回找到的上一个匹配的字符。要报告空字符串的成功搜索,此方法返回空字符串。如果解析器尚未执行查找或先前的查找操作失败,则会抛出异常IllegalStateException
。 -
该方法
String group(int group)
与前面的方法类似,不同之处在于它返回上一个匹配的字符,由参数指定的组号捕获group
。请注意,这group(0)
相当于group()
. 如果模板没有具有给定编号的捕获组,则该方法将引发异常IndexOutOfBoundsException
。如果解析器尚未执行查找或先前的查找操作失败,则会抛出异常IllegalStateException
。 -
该方法
String group(String name)
返回由名称组捕获的上一个匹配项的字符。如果捕获的组名不在模板中,则会抛出异常IllegalArgumentException
。如果解析器尚未执行查找或先前的查找操作失败,则会抛出异常IllegalStateException
。
groupCount()
和方法的使用group(int group)
:
Pattern p = Pattern.compile("(.(.(.)))");
Matcher m = p.matcher("abc");
m.find();
System.out.println(m.groupCount());
for (int i = 0; i <= m.groupCount(); i++)
System.out.println(i + ": " + m.group(i));
执行结果:
3
0: abc
1: abc
2: bc
3: c
确定比赛位置的方法
该类Matcher
提供了几种返回匹配开始和结束位置的方法:
-
该方法
int start()
返回找到的上一个匹配项的起始位置。如果解析器尚未执行查找或先前的查找操作失败,则会抛出异常IllegalStateException
。 -
该方法
int start(int group)
与前面的方法类似,但返回为参数 指定编号的组找到的上一个匹配项的起始位置group
。如果模板没有具有给定编号的捕获组,则该方法将引发异常IndexOutOfBoundsException
。如果解析器尚未执行查找或先前的查找操作失败,则会抛出异常IllegalStateException
。 -
该方法
int start(String name)
与前面的方法类似,但返回为名为 的组找到的上一个匹配项的起始位置name
。如果捕获的组name
不在模板中,则会抛出异常IllegalArgumentException
。如果解析器尚未执行查找或先前的查找操作失败,则会抛出异常IllegalStateException
。 -
该方法
int end()
返回上一次找到的匹配的最后一个字符的位置加1。如果匹配器尚未执行匹配或上一次搜索操作失败,则会抛出异常IllegalStateException
。 -
该方法
int end(int group)
与前面的方法类似,但返回为参数 指定编号的组找到的上一个匹配项的结束位置group
。如果模板没有具有给定编号的捕获组,则该方法将引发异常IndexOutOfBoundsException
。如果解析器尚未执行查找或先前的查找操作失败,则会抛出异常IllegalStateException
。 -
该方法
int end(String name)
与前面的方法类似,但返回为名为 的组找到的上一个匹配项的结束位置name
。如果捕获的组name
不在模板中,则会抛出异常IllegalArgumentException
。如果解析器尚未执行查找或先前的查找操作失败,则会抛出异常IllegalStateException
。
Pattern p = Pattern.compile("(.(.(.)))");
Matcher m = p.matcher("abcabcabc");
while (m.find())
{
System.out.println("Найдено " + m.group(2));
System.out.println(" начинается с позиции " + m.start(2) +
" и заканчивается на позиции " + (m.end(2) - 1));
System.out.println();
}
该示例的输出如下:
Найдено bc
начинается с позиции 1 и заканчивается на позиции 2
Найдено bc
начинается с позиции 4 и заканчивается на позиции 5
Найдено bc
начинается с позиции 7 и заканчивается на позиции 8
PatternSyntaxException 类的方法
该类的实例PatternSyntaxException
描述了正则表达式中的语法错误。从方法compile()
和matches()
类中抛出此类异常Pattern
,并通过以下构造函数形成: PatternSyntaxException(String desc, String regex, int index)
该构造函数存储指定的描述 ( desc
)、正则表达式( regex
) 以及发生语法错误的位置。如果语法错误的位置未知,则该值index
设置为-1
。最有可能的是,您永远不需要创建PatternSyntaxException
. 但是,在创建格式化错误消息时,您将需要提取上述值。为此,您可以使用以下方法:
- 该方法
String getDescription()
返回语法错误的描述。 - 该方法
int getIndex()
返回错误发生的位置,如果位置未知,则返回 -1。 - 该方法
String getPattern()
返回无效的正则表达式。
String getMessage()
返回一个多行字符串,其中包含从先前方法返回的值以及模板中语法错误发生位置的可视指示。什么是语法错误?下面是一个示例: 在本例中,我们忘记在嵌套标志表达式中java RegexDemo (?itree Treehouse
指定右括号元字符 ( )。)
这是此错误的输出:
regex = (?itree
input = Treehouse
Неправильное регулярное выражение: Unknown inline modifier near index 3
(?itree
^
Описание: Unknown inline modifier
Позиция: 3
Неправильный шаблон: (?itree
使用 Regex API 构建有用的正则表达式应用程序
正则表达式使您能够创建功能强大的文本处理应用程序。在本节中,我们将向您展示两个方便的应用程序,希望它们能够鼓励您进一步探索 Regex API 类和方法。第二个附录介绍了 Lexan:一个用于执行词法分析的可重用代码库。正则表达式和文档
文档编制是开发专业软件时的强制性任务之一。幸运的是,正则表达式可以在文档创建的许多方面为您提供帮助。清单 1 中的代码从源文件中提取包含单行和多行 C 风格注释的行,并将它们写入另一个文件。为了使代码正常工作,注释必须位于同一行。清单 1. 检索评论import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
public class ExtCmnt
{
public static void main(String[] args)
{
if (args.length != 2)
{
System.err.println("Способ применения: java ExtCmnt infile outfile");
return;
}
Pattern p;
try
{
// Следующий шаблон определяет многострочные комментарии,
// располагающиеся в одной строке (например, /* одна строка */)
// и однострочные комментарии (например, // Howая-то строка).
// Комментарий может располагаться в любом месте строки.
p = Pattern.compile(".*/\\*.*\\*/|.*//.*$");
}
catch (PatternSyntaxException pse)
{
System.err.printf("Синтаксическая ошибка в регулярном выражении: %s%n", pse.getMessage());
System.err.printf("Описание ошибки: %s%n", pse.getDescription());
System.err.printf("Позиция ошибки: %s%n", pse.getIndex());
System.err.printf("Ошибочный шаблон: %s%n", pse.getPattern());
return;
}
try (FileReader fr = new FileReader(args[0]);
BufferedReader br = new BufferedReader(fr);
FileWriter fw = new FileWriter(args[1]);
BufferedWriter bw = new BufferedWriter(fw))
{
Matcher m = p.matcher("");
String line;
while ((line = br.readLine()) != null)
{
m.reset(line);
if (m.matches()) /* Должна соответствовать вся строка */
{
bw.write(line);
bw.newLine();
}
}
}
catch (IOException ioe)
{
System.err.println(ioe.getMessage());
return;
}
}
}
清单 1 中的方法main()
首先检查命令行语法是否正确,然后将用于检测单行和多行注释的正则表达式编译到类对象中Pattern
。如果没有引发异常PatternSyntaxException
,该方法main()
将打开源文件,创建目标文件,获取匹配器来匹配根据模式读取的每一行,然后逐行读取源文件。对于每一行,它都与注释模式匹配。如果成功,该方法main()
会将字符串(后跟换行符)写入目标文件(我们将在未来的 Java 101 教程中介绍文件 I/O 逻辑)。按如下方式编译清单 1: javac ExtCmnt.java
使用文件作为输入运行应用程序ExtCmnt.java
: java ExtCmnt ExtCmnt.java out
您应该在文件输出中得到以下结果:
// Следующий шаблон определяет многострочные комментарии,
// располагающиеся в одной строке (например, /* одна строка */)
// и однострочные комментарии (например, // Howая-то строка).
// Комментарий может располагаться в любом месте строки.
p = Pattern.compile(".*/\\*.*\\*/|.*//.*$");
if (m.matches()) /* Должна соответствовать вся строка */
在模式字符串 中.*/\\*.*\\*/|.*//.*$
,管道元字符|
充当逻辑 OR 运算符,指示匹配器应使用给定正则表达式构造的左操作数在匹配器文本中查找匹配项。如果没有匹配项,匹配器将使用给定正则表达式构造中的正确操作数进行另一次搜索尝试(捕获组中的括号元字符也形成逻辑运算符)。 Java 中的正则表达式,第 5 部分
GO TO FULL VERSION