Java开发笔记(三十七)利用正则串分割字符串
前面介绍了处理字符串的常用方法,还有一种分割字符串的场景也很常见,也就是按照某个规则将字符串切割为若干子串。分割规则通常是指定某个分隔符,根据字符串内部的分隔符将字符串进行分割,例如逗号、空格等等都可以作为字符串的分隔符。正好String类型提供了split方法用于切割字符串,只要字符串变量调用split方法,并把分隔符作为输入参数,该方法即可返回分割好的字符串数组。
下面的split调用代码例子演示了如何按照逗号和空格切割字符串:
// 通过逗号分割字符串
private static void splitByComma() {
String commaStr = "123,456,789";
// 利用split方法指定按照逗号切割字符串
String[] commaArray = commaStr.split(",");
for (String item : commaArray) {
System.out.println("comma item = "+item);
}
} // 通过空格分割字符串
private static void splitBySpace() {
String spaceStr = "123 456 789";
// 利用split方法指定按照空格切割字符串
String[] spaceArray = spaceStr.split(" ");
for (String item : spaceArray) {
System.out.println("space item = "+item);
}
}
除了逗号和空格以外,点号和竖线也常常用来分隔字符串,但是对于点号和竖线,split方法的调用代码不会得到预期的结果。相反,split(".")无法得到分割后的字符串数组,也就是说结果的字符串数组为空;而split("|")分割得到的字符串数组,每个数组元素只有一个字符,其结果类似于toCharArray。究其原因,缘于split方法的输入参数理应是个正则串,并非普通的分隔字符。由于点号和竖线都是正则串的保留字符,因此无法直接在正则串中填写,必须进行转义处理方可。如同回车符和换行符在普通字符串中通过前缀的反斜杆转义那样(回车符对应\r,换行符对应\n),正则字符串通过在原字符前面添加两个反斜杆来转义,像点号字符在正则串中对应的转义符为“\\.”,而竖线在正则串中对应的转义符为“\\|”。经过转移处理之后,通过点号和竖线切割字符串的正确代码写法如下所示:
// 通过点号分割字符串
private static void splitByDot() {
String dotStr = "123.456.789";
// split(".")无法得到分割后的字符串数组
//String[] dotArray = dotStr.split(".");
// 点号是正则串的保留字符,需要进行转义(在点号前面加两个反斜杆)
String[] dotArray = dotStr.split("\\.");
for (String item : dotArray) {
System.out.println("dot item = "+item);
}
} // 通过竖线分割字符串
private static void splitByLine() {
String lineStr = "123|456|789";
// split("|")分割得到的字符串数组,每个数组元素只有一个字符,类似于toCharArray的结果
//String[] lineArray = lineStr.split("|");
// 竖线是正则串的保留字符,需要进行转义(在竖线前面加两个反斜杆)
String[] lineArray = lineStr.split("\\|");
for (String item : lineArray) {
System.out.println("line item = "+item);
}
}
竖线符号之所以被定为正则串的保留字符,是因为它在正则表达式里起到了“或”的判断作用,例如正则串“,| ”表示逗号和空格都是满足条件的分隔符;一个字符串如果同时包含一个逗号和一个空格,那么按照“,| ”切割的结果将是长度为3的字符串数组;也就是说,原始串被逗号分割一次后又被空格分割一次,这样一共分割两次最终得到了三个子串。下面的代码演示了使用正则串“,| ”切割字符串的效果:
// 利用竖线同时指定多个串来分割字符串
private static void splitByMixture() {
String mixtureStr = "123,456 789";
// 正则串里的竖线表示“或”,竖线左边和右边的字符都可以用来分割字符串
String[] mixtureArray = mixtureStr.split(",| ");
for (String item : mixtureArray) {
System.out.println("mixture item = "+item);
}
}
当然,正则串中的保留字符不仅包括点号和竖线,还包括好些常见的符号,比如加号(+)、星号(*)、横线(-),在正则串中均需进行转义。其中加号的正则转义符为“\\+”,星号的正则转义符为“\\*”,横线的正则转义符为“\\-”。这么估摸下,加减乘除的四则运算符号,只有除法的斜杆符(/)、取余数的百分号(%)无需转义处理。倘若有个字符串,要求以四则运算的五个符号进行切割,则需通过竖线把这几个转义后的字符加以连接,构成形如“\\+|\\*|\\-|/|%”的正则串。于是按照加减乘除符号切割字符串的代码就变为下面这样:
// 通过算术的加减乘除符号来分割字符串
private static void splitByArith() {
String arithStr = "123+456*789-123/456%789";
// 正则串里的加号、星号、横线都要转义,加减乘除符号之间通过竖线隔开
String[] arithArray = arithStr.split("\\+|\\*|\\-|/|%");
for (String item : arithArray) {
System.out.println("arith item = "+item);
}
}
分割用的正则串,不单单是一个个字符,还支持好几个字符组成的字符串。譬如“(1)”、“(2)”、“(3)”都可以作为分隔串,注意圆括号内部的数字可以是0到9,如此一来,从“(0)”到“(9)”的分隔串合集岂不是要写成以下这般:“(0)|(1)|(2)|(3)|(4)|(5)|(6)|(7)|(8)|(9)”?然而以上正则串的写法有两个错误:
1、圆括号也是正则表达式的保留字符,所以不能直接在正则串中书写“(”和“)”,而必须写成转义形式“\\(”和”“\\)”。
2、作为保留字符的圆括号,其作用类似数值计算之时的圆括号,都是通过圆括号把括号内外的运算区分开。而竖线符号“|”的或运算优先级不如圆括号,因此每逢复杂一点的或运算,应当把圆括号放在整个逻辑运算式子的外面。
综合以上两点,修正之后的正则串应该改成下列形式:“\\((0|1|2|3|4|5|6|7|8|9)\\)”。可是该式子的竖线太多,意思仅仅是获取0到9之间的某个数字之一,针对这种情况,正则表达式引入了另外一种简化的写法,即通过方括号包裹0123456789,形如“\\([0123456789]\\)”,同样指代0到9之间的某个数字,从而省略了若干个竖线。进一步说,日常生活中0到9,常常写做“0-9”,于是对应更简单的正则串“\\([0-9]\\)”。
其实0到9正好涵盖了所有的一位数字,对于一位数字而言,正则表达式提供了专门的表达式“\\d{1}”。式子前面的“\\d”代表某个数字,式子后面的“{1}”代表字符数量是1位。推而广之,“\\d{2}”表示两位数字,“\\d{3}”表示三位数字,等等。像这个正则例子只有一位数字,甚至尾巴的“{1}”都可以去掉,因为“\\d”默认就是一位数字。
一口气介绍了许多种从0到9的正则表达串,接下来不妨逐一验证这些正则串是否有效,验证用的代码例子如下所示:
// 通过圆括号及其内部数字来分割字符串
private static void splitByBracket() {
String bracketStr = "(1)123;(2)456;(3)789;";
// 圆括号也是正则串的保留字符,0到9这九个数字使用竖线隔开
//String[] bracketArray = bracketStr.split("\\((0|1|2|3|4|5|6|7|8|9)\\)");
// 利用方括号聚集一群字符,表示这些字符之间是“或”的关系,故而可省略竖线
//String[] bracketArray = bracketStr.split("\\([0123456789]\\)");
// 连续的数字可使用横线连接首尾数字,例如“0-9”表示从0到9之间的所有数字
//String[] bracketArray = bracketStr.split("\\([0-9]\\)");
// 利用“\\d”即可表达0到9的数字,后面的{1}表示1位数字,依此类推{3}表示三位数字
//String[] bracketArray = bracketStr.split("\\(\\d{1}\\)");
// “\\d”默认就是1位数字,此时后面的{1}可直接略去
String[] bracketArray = bracketStr.split("\\(\\d\\)");
for (String item : bracketArray) {
System.out.println("bracket item = "+item);
}
}
上述的几种正则串,只能表达从“(0)”到“(9)”的分隔串,然而圆括号内部还可能是两位数字或者三位数字,比如“(10)”、“(12)”、“(001)”这样。对于数字位数不固定的情况,可以把“\\d”改为“\\d+”,末尾多出来的加号,表示前面的字符允许有一位,也允许有多位。此时正则串添加了加号的字符串切割代码见下:
// 通过特殊符号的加号来分割字符串
private static void splitWithPlus() {
String bracketStr = "(1)123;(2)456;(13)789;";
// 正则串里的加号表示可以有1到多个前面的字符
String[] bracketArray = bracketStr.split("\\(\\d+\\)");
for (String item : bracketArray) {
System.out.println("plus item = "+item);
}
}
上面说的位数不固定,毕竟至少还有一位。假设现在某个字符不但位数不确定,甚至还可能没有该字符(位数为0),采用写法“\\d+”就无法奏效了。要想满足位数可有可无的情况,需将末尾的加号换成星号,也就是改成“\\d*”,此时改用星号的字符串切割代码变为下面这般:
// 通过特殊符号的星号来分割字符串
private static void splitWithStar() {
String bracketStr = "()123;(2)456;(13)789;";
// 正则串里的星号表示可以有0到多个前面的字符
String[] bracketArray = bracketStr.split("\\(\\d*\\)");
for (String item : bracketArray) {
System.out.println("star item = "+item);
}
}
到目前位置,分隔符还仅限于标点和数字,如果引入英文字母作为分隔串,又该如何书写呢?注意英文字母区分大小写,因而使用“a-z”表示所有的小写字母,使用“A-Z”表示所有的大写字母。如果采纳“(a)”、“(B)”、“(c)”这种大小写混合的分隔串,就得通过正则串“\\([a-zA-Z]\\)”来表达,对应的字符串切割代码如下所示:
// 通过大小写字母来分割字符串
private static void splitWithLetter() {
String bracketStr = "(a)123;(B)456;(c)789;";
// 在正则串中表达小写字母和大写字母
String[] bracketArray = bracketStr.split("\\([a-zA-Z]\\)");
for (String item : bracketArray) {
System.out.println("letter item = "+item);
}
}
现在有个麻烦的业务场景,圆括号内部不但可能是数字和字母,还可能是其它标点符号,这下难不成把众多标点符号一个个罗列出来?要知道标点符号可没有“0-9”、“a-z”、“A-Z”的简单写法噢。不过这难不倒强大的正则表达式,因为点号作为正则的保留字符,它代表了除回车\r和换行\n以外的其它字符,所以使用“\\(.\\)”即可表达符合要求的任意字符了,当然是被圆括号包裹着的、除了回车\r和换行\n以外的任意字符。下面便是匹配前述场景的字符串切割代码例子:
// 通过特殊符号的点号来分割字符串
private static void splitWithDot() {
String bracketStr = "(1)123;(B)456;(%)789;";
// 正则串里的点号表示除了回车\r和换行\n以外的其它字符
String[] bracketArray = bracketStr.split("\\(.\\)");
for (String item : bracketArray) {
System.out.println("dot item = "+item);
}
}
更多Java技术文章参见《Java开发笔记(序)章节目录》
Java开发笔记(三十七)利用正则串分割字符串的更多相关文章
- Java开发笔记(一百零八)JSON串的定义和解析
前面提到URL尾巴支持添加请求参数,具体格式形如“参数A名称=A参数值&参数B名称=B参数值”,可是这种格式只能传递简单的键值对信息,不能传递结构化数据,也无法传递数组形式的参数,因而它不适用 ...
- Java开发学习(三十七)----SpringBoot多环境配置及配置文件分类
一.多环境配置 在工作中,对于开发环境.测试环境.生产环境的配置肯定都不相同,比如我们开发阶段会在自己的电脑上安装 mysql ,连接自己电脑上的 mysql 即可,但是项目开发完毕后要上线就需要该配 ...
- Java开发笔记(四十)日期与字符串的互相转换
前面介绍了如何通过Date工具获取各个时间数值,但是用户更喜欢形如“2018-11-24 23:04:18”这种结构清晰.简洁明了的字符串,而非啰里八唆依次汇报每个时间单位及其数值的描述.既然日期时间 ...
- Java开发笔记(十七)各得其所的多路分支
前面提到条件语句的标准格式为“if (条件) { /* 条件成立时的操作代码 */ } else { /* 条件不成立时的操作代码 */ }”,乍看之下仿佛只有两个分支,一个是条件成立时的分支,另一个 ...
- Java开发笔记(序)章节目录
现将本博客的Java学习文章整理成以下笔记目录,方便查阅. 第一章 初识JavaJava开发笔记(一)第一个Java程序Java开发笔记(二)Java工程的帝国区划Java开发笔记(三)Java帝国的 ...
- Java开发笔记(三十八)利用正则表达式校验字符串
前面多次提到了正则串.正则表达式,那么正则表达式究竟是符合什么定义的字符串呢?正则表达式是编程语言处理字符串格式的一种逻辑式子,它利用若干保留字符定义了形形色色的匹配规则,从而通过一个式子来覆盖满足了 ...
- Java开发笔记(九十七)利用Runnable启动线程
前面介绍了线程的基本用法,按理说足够一般的场合使用了,只是每次开辟新线程,都得单独定义专门的线程类,着实开销不小.注意到新线程内部真正需要开发者重写的仅有run方法,其实就是一段代码块,分线程启动之后 ...
- Java开发笔记(一百三十七)JavaFX的标签
前面介绍了JavaFX的窗口框架,其中舞台.场景.窗格都能与AWT/Swing体系的相关概念一一对应,不仅如此,JavaFX的常见控件也能在Swing中找到相应的控件.比如JavaFX的按钮控件名叫B ...
- Java开发笔记(三十四)字符串的赋值及类型转换
不管是基本的char字符型,还是包装字符类型Character,它们的每个变量只能存放一个字符,无法满足对一串字符的加工.为了能够直接操作一连串的字符,Java设计了专门的字符串类型String,该类 ...
随机推荐
- Oracle 函数 Function
定义 函数用于计算和返回一个结果值,把经常需要进行的计算写成函数,函数的调用是表达式的一部分. 函数与过程在创建的形式上有些相似,也是编译后放在内存中供用户使用. 函数必须有一个返回值 ...
- git命令别名(Alias)
每次切换分支: git ckeckout branch_name 等命令费时又费力,git 别名配置起来: 别名配置: git config --global alias.ck ckeckout 其他 ...
- unittest生产html测试报告
需要添加HTMLTestRunner.py文件,我用的ubuntu16.04下的python3.5.2,所以我放在/usr/lib/python3.5下 import unittest import ...
- ndk编译faac生成库
1.编译脚本如下: NDK=/opt/android-ndk-r9d TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.6/prebuilt/linu ...
- 别以为真懂Openstack: 虚拟机创建的50个步骤和100个知识点(4)
六.Libvirt 对于Libvirt,在启动虚拟机之前,首先需要define虚拟机,是一个XML格式的文件 列出所有的Instance # virsh list Id Name ...
- SQL Server Service Broker创建单个数据库会话(消息队列)
概述 SQL Server Service Broker 用来创建用于交换消息的会话.消息在目标和发起方这两个端点之间进行交换.消息用于传输数据和触发消息收到时的处理过程.目标和发起方既可以在同一数据 ...
- 【RL-TCPnet网络教程】第25章 DHCP动态主机配置协议基础知识
第25章 DHCP动态主机配置协议基础知识 本章节为大家讲解DHCP(Dynamic Host Configuration Protocol,动态主机配置协议),通过前面章节对TCP和UDP ...
- Vue(day2)
一.过滤器 Vue中可以自定义过滤文本插值的过滤器.目前有两个地方可以使用: 插值文本{{ var }}中使用. 在v-bind中使用.( 2.1.0+ ) 用法:使用管道连接符 | 将需要过滤的文本 ...
- [Swift]LeetCode336. 回文对 | Palindrome Pairs
Given a list of unique words, find all pairs of distinct indices (i, j) in the given list, so that t ...
- [Swift]LeetCode524. 通过删除字母匹配到字典里最长单词 | Longest Word in Dictionary through Deleting
Given a string and a string dictionary, find the longest string in the dictionary that can be formed ...