01:正则表达式 在 任何一门语言都包括 ,至于正则表达式的学习 ,可以专门针对。
02:在String中使用的正则表达式。
a:String中所使用到的 正则表达式的方法包括:replaceFirst() replaceAll() split()这些方法。
b:除此之外的 方法 不可以使用正则 表达式。
03:解释JavaSE中的 String类的split()方法:
public String[] split(String regex , int limit)
根据 匹配 给定的正则表达式 来 拆分 此字符串。
此方法返回的 数组 包含此字符串的每个子字符串,
这些子字符串 由 另一个 匹配 给定的表达式 的 子字符串 终止 或 由 字符串结束 来终止。
//开始:是从当前字符串的 开头开始的
//结束: 由 下一个匹配的字符串结束 ,或者一直到 传递字符串的 结束位置 。
注意: 可能会引起 空字符串的情况,如下解释。
数组中的子字符串按它们在此字符串中的顺序排列。如果表达式不匹配输入的任何部分,则结果数组只具有一个元素,即当前字符串。
limit 参数 控制 模式 应用的 次数,因此影响结果数组的长度。如果该限制 n 大于 0,则模式将被最多应用 n - 1 次,数组的长度将不会大于 n, 而且 数组的最后项 将包含 超出 最后匹配的定界符的所有输入。
如果 n 为非正,则模式将被应用尽可能多的次数,而且数组可以是任意长度。并且结尾空字符串将被丢弃。
如果 n 为零, 则模式将被应用尽可能多的次数,数组可有任何长度,并且结尾空字符串将被丢弃。
例如,字符串 “boo:and:foo” 使用这些参数可生成下列结果:
-
Regex Limit 结果
- 2 { “boo”, “and:foo” }
- 5 { “boo”, “and”, “foo” }
-
-2 { “boo”, “and”, “foo” }
o 5 { “b”, “”, “:and:f”, “”, “” } //结尾的 空字符串并没有被丢弃
o -2 { “b”, “”, “:and:f”, “”, “” } //结尾的 空字符串并没有被丢弃
o 0 { “b”, “”, “:and:f” } //结尾的空字符串【2个】 被丢弃!!!
这种形式的方法调用 str.split(regex, n) 产生与以下表达式完全相同的结果:
Pattern.compile(regex).split(str, n)
replaceAll 和 replaceFirst 方法 使用的是正则表达式 ,但是正则表达式也属于字符串 ,这里也可以使用 具体的字符串的形式【此时具体的字符串 同样代表 正则表达式】 ,java教材上面写的是具体的字符串的形式。
====》生成新的对象, 但是并没有改变原来的字符串
第一个方法是替换,但是替换的是char,不是String。依然替换的所有的字符。
第二个方法是替换的CharSequence(包括String, StringBuffer, StringBuilder),但是替换的是全部。
第三个replaceAll是替换全部的 字符串形式的正则表达式,
第四个是 替换字符串中第一个匹配的项,但是人家名字写得明明白白的replaceFirst,而且替换的也是正则表达式。
//但是牢记: 第一个参数可以是 字符【char】 字符串【String】 字符序列【charSequence】或者是 正则表达式的字符串形式
第二个参数 必须是 字符串的形式。
解释:
第一个方法:执行思路:我们用后面的 字符 替换 字符串 中出现的 所有的 第一个形式参数的字符。
//使用的是 字符串中的包含
第二个方法: 执行思路 同上
第三个方法: 第一个形式参数 必须是 一个正则表达式的字符串表示形式,然后执行字符串对象的 包含功能, 将当前字符串中 包含 正则表达式的 匹配项 全部替换掉。
第四个方法: 执行思路同上 , 但是 仅仅 替换 包含在当前字符串中的正则表达式的 第一个匹配项。
//注意:此时 我们一定要注意,在使用replaceAll的时候 传递的如果是要给字符串,那么此时的字符串 被解释成为一个 正则表达式 而存在。 在一般情况下 确定的字符串 如果被当做是一个 正则表达式 而存在的话, 那么就表示 必须匹配当前的 字符串的一种形式 而没有了 正则表达式的 多种形式的可能。
因此我们总结:确定的字符串 也是正则表达式的一种特殊形式, 只不过与大多数的正则表达式而言 , 没有那么多变化,就这一种可能。
public static void main(String args[]) {
String value = “cat” ;
System.out.println(value.matches(".at")); //true 可以匹配 cat fat kat mat等等。
}
public static void main(String args[]) {
String value = “cat” ;
System.out.println(value.matches(“cat”));//true 只可以匹配cat
}
//具体的正则表达式 可以参考 之前的网络下载资料 和 总结的笔记 以及 教材《必知必会》
matches()匹配 正则表达式:
语法 :public boolean matches(String regex)
参数:regex – 匹配字符串的正则表达式。
返回值 : 在字符串匹配给定的正则表达式时,返回 true。指的是 传递的所有的字符串 跟模式完全 吻合。
实例
public class Test {
public static void main(String args[]) {
String Str = new String(“www.w3cschool.cn”);
System.out.print("返回值 :" );
System.out.println(Str.matches("(.*)youj(.*)"));//false
System.out.print("返回值 :" );
System.out.println(Str.matches("(.*)google(.*)"));//false
System.out.print("返回值 :" );
System.out.println(Str.matches("www(.*)"));//true
}
}
//备注:这里我们需要 确切的知道 java的正则正则表达式 的具体写法 , 必须知道 java的正则表达式的 标准写法 和 要求。
在java中正则表达式 如果使用 字符串的形式来写 就必须在 正则表达式 前后 加上双引号, 跟js的写法不一样 , 不可以 在后面写 gim 来表示 全局 忽略大小写 多行。
用字符串的形式去表示一个 正则表达式 比如:
匹配 email的格式: String Email_regex= “\w+@\w+\.\w{2,3}”;
只能输入零和非零开头的数字:String value = “^(0|[1-9][0-9]*)
”
只
能
输
入
有
1
−
3
位
小
数
的
正
实
数
:
S
t
r
i
n
g
v
a
l
u
e
=
“
[
0
−
9
]
+
(
.
[
0
−
9
]
1
,
3
)
?
” 只能输入有1-3位小数的正实数:String value = “^[0-9]+(.[0-9]{1,3})?
”只能输入有1−3位小数的正实数:Stringvalue=“[0−9]+(.[0−9]1,3)?”
//注意:如果想实现 忽略大小写 多行 等等 还有捕获组 这些牛逼的 要求 就需要 java提供的 正则表达式的类【Pattern Matcher】。java正则表达式通过java.util.regex包下的Pattern和Matcher类实现
Pattern类:
//上边的 CANON_EQ CASE_INSENSITIVE COMMENTS DOTALL LITERAL MULTILINE UNICODE_CASE UNIX_LINES 写在 Patter.compile(String regex , int flags)的flags中。
Pattern 类包含多个标志(int 类型),这些标志可以控制Pattern 匹配模式的方式。
compile()方法:
Pattern类用于创建 一个 正则表达式 实例对象 , 也可以说是创建一个匹配模式。
可以通过两个静态方法创建:compile(String regex)和compile(String regex,int flags),
其中regex是正则表达式,flags为可选模式(如:Pattern.CASE_INSENSITIVE 忽略大小写),==>来创建正则表达式的 实例对象 。除此之外没有别的方法 来创建正则表达式 对象 , 这可以通过静态方法来创建 正则表达式对象。
matches()方法:
Pattern类也自带一个静态匹配方法matches(String regExp, CharSequence input),但 只能 进行全字符串匹配 并且 只能 返回 是否 匹配上的 boolean值
//Pattern 类中 只有 这个一个 matches()方法 ,正则表达式 是第一个 形式参数 ,传递的字符串是第二个形式参数。 用于测试 字符串是否 跟模式完全匹配。
实例:
String test1 = “Java”;
String test2 = “Java123456”;
System.out.println(Pattern.matches(“Java”,test1));//返回true
System.out.println(Pattern.matches(“Java”,test2));//返回false
//全局匹配: 使用 第一个参数的 regExp 完全跟input【全部的input输入】 进行匹配 。
split()方法:
public String[] split(CharSequence input, int limit)
//但是一定要 明白 这个是 正则表达式 实例对象 所具备的 split()方法。
根据 匹配 给定的正则表达式 来 拆分 此字符串。
此方法返回的 数组 包含此字符串的每个子字符串,
这些子字符串 由 另一个 匹配 给定的表达式 的 子字符串 终止 或 由 字符串结束 来终止。
//开始:是从当前字符串的 开头开始的
//结束: 由 下一个匹配的字符串结束 ,注意: 可能会引起 空字符串的情况,如下情况。
数组中的子字符串按它们在此字符串中的顺序排列。如果表达式不匹配输入的任何部分,则结果数组只具有一个元素,即当前字符串。
limit 参数 控制 模式 应用的 次数,因此影响结果数组的长度。如果该限制 n 大于 0,则模式将被最多应用 n - 1 次,数组的长度将不会大于 n, 而且 数组的最后项 将包含 超出 最后匹配的定界符的所有输入。
如果 n 为非正,则模式将被应用尽可能多的次数,而且数组可以是任意长度。并且结尾空字符串将被丢弃。
如果 n 为零, 则模式将被应用尽可能多的次数,数组可有任何长度,并且结尾空字符串将被丢弃。
例如,字符串 “boo:and:foo” 使用这些参数可生成下列结果:
-
Regex Limit 结果
- 2 { “boo”, “and:foo” }
- 5 { “boo”, “and”, “foo” }
-
-2 { “boo”, “and”, “foo” }
o 5 { “b”, “”, “:and:f”, “”, “” } //结尾的 空字符串并没有被丢弃
o -2 { “b”, “”, “:and:f”, “”, “” } //结尾的 空字符串并没有被丢弃
o 0 { “b”, “”, “:and:f” } //结尾的空字符串【2个】 被丢弃!!!
参数:
input - 要拆分的字符序列。
limit - 结果阈值,如上文中所述。
Matcher类的解释:
结合Pattern 和 Matcher 类的 思路。
①将正则表达式封装成对象 : Pattern p = Pattern.compile(regex);
②让正则对象和要操作的字符串相关联 -----> 匹配器引擎 : Matcher m = p.matcher(str) ;
于是 我们得到 了一个 匹配器引擎。
matcher()方法:
//创建Matcher
通过Pattern的实例对象 的 matcher() 方法创建一个Matcher。 //括号里的参数 是 要被匹配的字符串。
String text =
"This is the text to be searched " +
“for occurrences of the http:// pattern.”;
String patternString = “.http://.”;
Pattern pattern = Pattern.compile(patternString);
Matcher matcher = pattern.matcher(text);
//到此为止 我们创建了一个 Pattern的 实例对象 pattern。 然后又通过 这个正则表达式的 pattern的实例变量 , 创造了一个 匹配引擎 匹配器。 ====>我们可以使用 匹配器 做很多事情。
match()方法:
Matcher 的 实例对象 的 matches() 方法用于在文本中匹配正则表达式
没有要被传递的参数,因为之前我们创建 正则表达式 对象的时候 传入了 正则表达式 字符串, 而在创建 别的Matcher对象的时候 有传入 了所需要比较的文本。
如果 传递整体的文本 匹配 完整的正则表达式 ,matches() 方法返回true。否则返回false。
matches() 方法不能用于查找正则表达式多次出现,只可以 在整体的情况下 使用一次。
lookAt()方法:
lookingAt() 与matches() 方法类似,最大的不同是,lookingAt()方法 对文本的开头 匹配正则表达式;它不需要匹配整个区域
而matches() 对 整个文本 匹配正则表达式。
换句话说,如果正则表达式匹配文本开头而不匹配整个文本,lookingAt() 返回true,而matches() 返回false。 示例:
String text =
"This is the text to be searched " +
“for occurrences of the http:// pattern.”;
String patternString = “This is the”;
Pattern pattern = Pattern.compile(patternString, Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(text);
System.out.println("lookingAt = " + matcher.lookingAt());
System.out.println("matches = " + matcher.matches());
上面的例子分别对文本开头和整个文本匹配正则表达式 “this is the”. 匹配文本开头的方法(lookingAt()) 返回true。
对整个文本匹配正则表达式的方法 (matches()) 返回false,因为 整个文本包含多余的字符,而 正则表达式要求文本精确匹配”this is the”,前后又不能有额外字符。
find() start() end()
//find() start() end()方法。
find() 方法用于 在 文本 中 查找出现 的匹配的正则表达式,文本是创建Matcher时,通过 Pattern.matcher(text) 方法传入的。
如果在文本中多次匹配,find() 方法返回第一个,之后每次调用 find() 都会返回下一个。
---->以此来实现 全局匹配。 这个find()方法 的目的 不是完全匹配 ,而是查找 字符串中 与模式匹配的 一段字符串。 也就是说 传递的字符串 中 有很多 子字符串 跟 这个模式匹配,
—>强调不是传递的字符串 跟这个 模式全部匹配。
//Matcher的实例对象 调用find()方法 , 返回 boolean值。true表示 有下一个匹配值 false表示没有下一匹配值。
//这个可是要注意了, 并不是 说 让传递的文本整体 跟 最外层的正则表达式整体 完全匹配的情况, 而是要 找到 传递的文本中 是否 包含正则表达式所匹配的字符串 , 且找到起始位置。
start() 和 end() 返回每次匹配的字串在整个文本中的开始和结束位置。实际上, end() 返回的是字符串末尾的后一位,这样,可以在把 start() 和 end() 的返回值直接用在String.substring() 里。
//我们就可以 找到 传递文本中 每一个 与 正则表达式 匹配的字符串喽,且可以通过 start() 和 end()的返回值 来拿到具体的 字符串了。
String text =
"This is the text which is to be searched " +
“for occurrences of the word ‘is’.”;
String patternString = “is”;
Pattern pattern = Pattern.compile(patternString);
Matcher matcher = pattern.matcher(text);
int count = 0;
while(matcher.find()) {
count++;
System.out.println("found: " + count + " : " + matcher.start() + " - " + matcher.end());
}
这个例子在文本中找到模式 “is” 4次,输出如下:
found: 1 : 2 - 4
found: 2 : 5 - 7
found: 3 : 23 - 25
found: 4 : 70 - 72
group()方法:
使用group(int groupNo) 方法访问一个分组。一个正则表达式可以有多个分组。每个分组由一对括号标记。想要访问正则表达式中某分组匹配的文本,可以把分组编号传入 group(int groupNo)方法。
group(0) 表示整个正则表达式,要获得一个有括号标记的分组,分组编号应该从1开始计算
如果使用group(x) 指定 要输出的分组的时候 没有匹配项 则输出 null。
//至此 我们可以拿到 传递字符串中 与 最外层的正则表达式匹配的 字符串 , 且可以拿到 这个匹配字符串的每个 分组, ====> 我们可以通过 稍微麻烦一些的办法 来实现 每个匹配字符串 中 每个分组 的替代 工作。
String text =
“John writes about this, and John Doe writes about that,” +
" and John Wayne writes about everything."
;
String patternString1 = "(John) (.+?) ";
Pattern pattern = Pattern.compile(patternString1);
Matcher matcher = pattern.matcher(text);
while(matcher.find()) {
System.out.println("found: " + matcher.group(1) +
" " + matcher.group(2));
}
注意代码中引用分组的方式。代码输出如下
found: John writes
found: John Doe
found: John Wayne
----->在使用 正则表达式 查找一个字符串中 是否 有匹配项的时候 我们 千万不可以在正则表达式中 加上 ^ $ 这样的位置字符。
Matcher实例对象的 replaceAll() replaceFirst() 方法:
//replaceAll() 方法 全部 替换 传递字符串中的 跟正则表达式 匹配得 子字符串;
//replaceFirst() 只替换第一个匹配的。
//在处理之前,Matcher 会先重置。所以这里的匹配表达式从文本开头开始计算。
//这个匹配 不是完全匹配 ,而是 查找传递字符串 中是否 存在 跟正则表达式 匹配的项, 如果存在 那么就全部替换掉。 注意:依然是 不能够 替换分组 ,替换的是 与 最外层正则表达式 匹配的 字符串。
---->但是我们可以解释 start() end()方法来替换分组。
示例如下
String text = “aabfooaabfooabfoob” ;
String patternString1 = “a*b”;
Pattern pattern = Pattern.compile(patternString1);
Matcher matcher = pattern.matcher(text);
String replaceAll = matcher.replaceAll("-");
System.out.println("replaceAll = " + replaceAll);
String replaceFirst = matcher.replaceFirst("-");
System.out.println("replaceFirst = " + replaceFirst);
输出如下:
replaceAll = -foo-foo-foo-
replaceFirst = -fooaabfooabfoob
appendReplacement() appendTail() 方法:
appendReplacement() 和 appendTail() 方法用于替换输入文本中的字符串短语,同时把替换后的字符串附加到一个 StringBuffer 中。
被Matcher的实例对象调用。
当find() 方法找到一个匹配项时,可以调用 appendReplacement() 方法,这会导致输入字符串被增加到StringBuffer 中,而且匹配文本被替换。 从上一个匹配文本结尾处开始,直到本次匹配文本会被拷贝【两次匹配 之间的 字符串 会被拷贝 , 且匹配的内容会被 第二个形式参数替换掉】。
---->:并不是传递字符串的 完全匹配, 而是全局字符串中 查找 与模式匹配的子字符串 , 然后替换, 注意 此时 匹配模式 匹配的是最外层的模式 简而言之 是 正则表达式 全部都匹配。
appendReplacement() 会记录拷贝StringBuffer 中的内容,可以持续调用find(),直到没有匹配项。
直到最后一个匹配项目,输入文本中剩余一部分没有拷贝到 StringBuffer.
这部分文本是从最后一个匹配项结尾,到文本末尾部分。通过调用 appendTail() 方法,可以把这部分内容拷贝到 StringBuffer 中.
我们是使用 Matcher的实例对象 来调用的 , 结合 find()方法 和 while()循环,来匹配 替换 和 添加 ,执行所有的 传递文本。
如果没有 找到任何 匹配项 则 stringBuffer实例对象大小是 0 ;
String text =
“John writes about this, and John Doe writes about that,” +
" and John Wayne writes about everything."
;
String patternString1 = "((John) (.+?)) ";
Pattern pattern = Pattern.compile(patternString1);
Matcher matcher = pattern.matcher(text);
StringBuffer stringBuffer = new StringBuffer();
while(matcher.find()){
matcher.appendReplacement(stringBuffer, "Joe Blocks ");
System.out.println(stringBuffer.toString());
}
matcher.appendTail(stringBuffer);
System.out.println(stringBuffer.toString());
注意我们在while循环中调用appendReplacement() 方法。在循环完毕后调用appendTail()。 代码输出如下:
Joe Blocks
Joe Blocks about this, and Joe Blocks
Joe Blocks about this, and Joe Blocks writes about that, and Joe Blocks
Joe Blocks about this, and Joe Blocks writes about that, and Joe Blocks
writes about everything.