Java正则表达式的十大问题

这篇文章总结了有关Java正则表达式的首要问题。由于它们是最常被问到的,您可能会发现它们也非常有用。

 

1.如何从字符串中提取数字?

使用正则表达式的一个常见问题是将所有数字提取到整数数组中。

 

在Java中,\d表示一个数字范围(0-9)。尽可能使用预定义的类将使代码更易于阅读,并消除格式错误的字符类引入的错误。有关更多详细信息,请参阅预定义字符类。请注意,第一个反斜杠\\d。如果在字符串文字中使用转义构造,则必须在反斜杠前面加上另一个反斜杠,以便编译字符串。这就是我们需要使用的原因\\d

 

List<Integer> numbers = new LinkedList<Integer>();
Pattern p = Pattern.compile("\\d+");
Matcher m = p.matcher(str);
while (m.find()) {
numbers.add(Integer.parseInt(m.group()));
}

2.如何按换行符拆分Java String?

根据您正在使用的操作系统,至少有三种不同的输入换行符的方法。

\ r表示CR(回车),用于Unix
\ n表示在Mac OS中使用的LF(换行)
\ r \ n表示在Windows中使用的CR + LF

因此,用新线分割字符串最直接的方法是

String lines[] = String.split("\\r?\\n");

但如果你不想要空行,你可以使用,这也是我最喜欢的方式:

String.split("[\\r\\n]+")

一种更加健壮的方式,实际上与系统无关,如下所示。但请记住,如果并排放置两个换行符,您仍然会得到空行。

String.split(System.getProperty("line.separator"));

3. Pattern.compile()的重要性

必须首先将指定为字符串的正则表达式编译为Pattern类的实例。图案。compile()方法是创建对象实例的唯一方法。因此,典型的调用序列

Pattern p = Pattern.compile("a*b");
Matcher matcher = p.matcher("aaaaab");
assert matcher.matches() == true;

基本上,模式compile()用于将正则表达式转换为有限状态机(请参阅编译器:原理,技术和工具(第2版))。但参与比赛的所有州都在比赛中。通过这种方式,可以重用Pattern p。许多匹配者可以共享相同的模式。

Matcher anotherMatcher = p.matcher("aab");
assert anotherMatcher.matches() == true;

模式matches()方法被定义为只使用正则表达式时的便利。此方法仍然使用compile()隐式获取Pattern的实例,并匹配字符串。因此,

boolean b = Pattern.matches("a*b", "aaaaab");

等同于上面的第一个代码,但是对于重复匹配,它效率较低,因为它不允许重用已编译的模式。

4.如何转义正则表达式的文本?

通常,正则表达式使用“\”来转义构造,但是在反斜杠之前用另一个反斜杠来编译Java字符串是很痛苦的。用户可以通过另一种方式将字符串文字传递给模式,例如“$ 5”。相反,写作\\$5或者[$]5,我们可以输入

Pattern.quote("$5");

5.为什么String.split()需要转义管道分隔符?

字符串split()在给定正则表达式的匹配项周围分割一个字符串。Java表达式支持影响模式匹配方式的特殊字符,称为元字符|是一个元字符,用于匹配几个可能的正则表达式中的单个正则表达式。例如,A|B表示A或者B。有关详细信息,请参阅垂直条或管道符号的交替。因此,要|用作文字,你需要通过\在它前面添加来逃避它,就像\\|

6.我们怎样才能匹配ñ b ň与Java正则表达式?

这是由一定数量的所有非空字符串的语言a的后面是数量相等b的,如abaabbaaabbb。这种语言可以显示为无上下文语法S→aSb | ab,因此是一种非常规语言。

但是,Java正则表达式实现可以识别的不仅仅是常规语言。也就是说,它们不是形式语言理论定义的“规则”。使用先行自引用匹配将实现它。在这里,我将首先给出最终的正则表达式,然后稍微解释一下。有关综合解释,我建议您阅读如何使用Java正则表达式匹配^ nb ^ n

Pattern p = Pattern.compile("(?x)(?:a(?= a*(\\1?+b)))+\\1");
// true
System.out.println(p.matcher("aaabbb").matches());
// false
System.out.println(p.matcher("aaaabbb").matches());
// false
System.out.println(p.matcher("aaabbbb").matches());
// false
System.out.println(p.matcher("caaabbb").matches());

我不想解释这个复杂的正则表达式的语法,而是想说一下它是如何工作的。

  1. 在第一次迭代中,它在第一次迭代时停止,a然后向前看(在跳过一些as后使用a*)是否存在b。这是通过使用来实现的(?:a(?= a*(\\1?+b)))。如果匹配,\1则自引用匹配将匹配内部括号元素,这是b第一次迭代中的单个元素。
  2. 在第二次迭代中,表达式将在第二次迭代时停止a,然后它向前看(再次跳过as)以查看是否存在b。但这次,\\1+b实际上相当于bb,因此两个b必须匹配。如果是这样,\1bb在第二次迭代后更改为。
  3. 在第n次迭代中,表达式在第n个停止,a并查看前面是否有n b

通过这种方式,表达式可以计算as 的数量并且如果b后面的s 的数量a相同则匹配。

7.如何用字符串中的单个空格替换2个或更多个空格并仅删除前导空格?

字符串replaceAll()用给定的替换替换与给定正则表达式匹配的每个子字符串。“2个或更多个空格”可以用正则表达式表示[ ]+。因此,以下代码将起作用。请注意,解决方案最终不会删除所有前导和尾随空格。如果您想删除它们,可以使用String。管道中的trim()

String line = " aa bbbbb ccc d ";
// " aa bbbbb ccc d "
System.out.println(line.replaceAll("[\\s]+", " "));

8.如何确定一个数字是否是正则表达式的素数?

public static void main(String[] args) {
// false
System.out.println(prime(1));
// true
System.out.println(prime(2));
// true
System.out.println(prime(3));
// true
System.out.println(prime(5));
// false
System.out.println(prime(8));
// true
System.out.println(prime(13));
// false
System.out.println(prime(14));
// false
System.out.println(prime(15));
}
public static boolean prime(int n) {
return !new String(new char[n]).matches(".?|(..+?)\\1+");
}

该函数首先生成n个字符,并尝试查看该字符串是否匹配.?|(..+?)\\1+。如果是素数,则表达式将返回false并且!将反转结果。

第一部分.?只是试图确保1不是引物。神奇的部分是使用反向引用的第二部分。(..+?)\\1+首先尝试匹配n个字符长度,然后重复几次\\1+

根据定义,素数是大于1的自然数,除了1和自身之外没有正除数。这意味着如果a = n * ma不是素数。n * m个可进一步解释“重复Ñ 倍”,而这正是正则表达式的作用:匹配Ñ通过使用字符的长度(..+?),然后重复它通过使用倍\\1+。因此,如果模式匹配,则数字不是素数,否则为。提醒那!将扭转结果。

9.如何拆分以逗号分隔的字符串但忽略引号中的逗号?

你已经达到正则表达式崩溃的程度。编写一个简单的拆分器更好更整洁,并根据需要处理特殊情况。

或者,您可以通过使用switch语句或if-else来模仿有限状​​态机的操作。附件是一段代码。

public static void main(String[] args) {
String line = "aaa,bbb,\"c,c\",dd;dd,\"e,e";
List<String> toks = splitComma(line);
for (String t : toks) {
System.out.println("> " + t);
}
}
private static List<String> splitComma(String str) {
int start = 0;
List<String> toks = new ArrayList<String>();
boolean withinQuote = false;
for (int end = 0; end < str.length(); end++) {
char c = str.charAt(end);
switch(c) {
case ',':
if (!withinQuote) {
toks.add(str.substring(start, end));
start = end + 1;
}
break;
case '\"':
withinQuote = !withinQuote;
break;
}
}
if (start < str.length()) {
toks.add(str.substring(start));
}
return toks;
}

10.如何在Java正则表达式中使用反向引用

反向引用是Java正则表达式中的另一个有用功能。

另外本人从事在线教育多年,将自己的资料整合建了一个QQ群,对于有兴趣一起交流学习java的初学者可以加群:732976516,里面有大神会给予解答,也会有许多的资源可以供大家学习分享,欢迎大家前来一起学习进步!

文章来源:https://www.programcreek.com/2013/10/top-10-questions-for-java-regular-expression/

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值