IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> 网络编程、正则表达式 -> 正文阅读

[网络协议]网络编程、正则表达式

网络编程、正则表达式

网络编程

1 概述

Java是 Internet 上的语言,它从语言级上提供了对网络应用程 序的支持,程序员能够很容易开发常见的网络应用程序。
Java提供的网络类库,可以实现无痛的网络连接,联网的底层 细节被隐藏在 Java 的本机安装系统里,由 JVM 进行控制。并 且 Java 实现了一个跨平台的网络库,程序员面对的是一个统一 的网络编程环境。

2 网络通信

UDP和TCP区别

  • TCP协议:
    ? 使用TCP协议前,须先建立TCP连接,形成传输数据通道
    ? 传输前,采用“三次握手”方式,点对点通信,是可靠的
    ? TCP协议进行通信的两个应用进程:客户端、服务端。
    ? 在连接中可进行大数据量的传输
    ? 传输完毕,需释放已建立的连接,效率低
  • UDP协议:
    ? 将数据、源、目的封装成数据包,不需要建立连接
    ? 每个数据报的大小限制在64K内
    ? 发送不管对方是否准备好,接收方收到也不确认,故是不可靠的
    ? 可以广播发送
    ? 发送数据结束时无需释放资源,开销小,速度快

通信双方地址
a)IP
b)端口号
一定的规则(即:网络通信协议。有两套参考模型)
c)OSI参考模型:模型过于理想化,未能在因特网上进行广泛推广
d)TCP/IP参考模型(或TCP/IP协议):事实上的国际标准。
2.1.通信要素1:IP地址
IP 地址:InetAddress
唯一的标识 Internet 上的计算机(通信实体)
本地回环地址(hostAddress):127.0.0.1 主机名(hostName):localhost
IP地址分类方式1:IPV4 和 IPV6
IPV4:4个字节组成,4个0-255。大概42亿,30亿都在北美,亚洲4亿。2011年初已经用尽。以点分十进制表示,如192.168.0.1
IPV6:128位(16个字节),写成8个无符号整数,每个整数用四个十六进制位表示, 数之间用冒号(:)分开,如:3ffe:3201:1401:1280:c8ff:fe4d:db39:1984
IP地址分类方式2:公网地址(万维网使用)和私有地址(局域网使用)。192.168. 开头的就是私有址址,范围即为192.168.0.0–192.168.255.255,专门为组织机 构内部使用
特点:不易记忆
端口号标识正在计算机上的进程
规定为16位整数
端口号与IP地址组合得出一个网络套接字:Socket

TCP

tcp三次握手:建立tcp连接,客户端和服务端之间客户端先发,两者交替总共发送三个包确立链接.
TCP四次挥手结束连接参考https://www.jianshu.com/p/ef892323e68f

Socket

利用套接字(Socket)开发网络应用程序早已被广泛的采用,以至于成为事实 上的标准。
网络上具有唯一标识的IP地址和端口号组合在一起才能构成唯一能识别的标 识符套接字。
通信的两端都要有Socket,是两台机器间通信的端点。
网络通信其实就是Socket间的通信。
Socket允许程序把网络连接当成一个流,数据在两个Socket间通过IO传输。
一般主动发起通信的应用程序属客户端,等待通信请求的为服务端。
Socket分类:
流套接字(stream socket):使用TCP提供可依赖的字节流服务数据报套接字(datagram socket):使用UDP提供“尽力而为”的数据报服务
常用方法
Socket类的常用构造器:
public Socket(InetAddress address,int port)创建一个流套接字并将其连接到指定IP 地址的指定端口号。
public Socket(String host,int port)创建一个流套接字并将其连接到指定主机上的指定端口号。
Socket类的常用方法:
public InputStream getInputStream()返回此套接字的输入流。可以用于接收网络消息
public OutputStream getOutputStream()返回此套接字的输出流。可以用于发送网络消息
public InetAddress getInetAddress()此套接字连接到的远程 IP 地址;如果套接字是未连接的,则返回 null。
public InetAddress getLocalAddress()获取套接字绑定的本地地址。 即本端的IP地址
public int getPort()此套接字连接到的远程端口号;如果尚未连接套接字,则返回 0。
public int getLocalPort()返回此套接字绑定到的本地端口。 如果尚未绑定套接字,则返回 -1。即本端的 端口号。
public void close()关闭此套接字。套接字被关闭后,便不可在以后的网络连接中使用(即无法重新连接 或重新绑定)。需要创建新的套接字对象。 关闭此套接字也将会关闭该套接字的 InputStream 和 OutputStream。
public void shutdownInput()如果在套接字上调用 shutdownInput() 后从套接字输入流读取内容,则流将 返回EOF(文件结束符)。 即不能在从此套接字的输入流中接收任何数据。
public void shutdownOutput()禁用此套接字的输出流。对于 TCP 套接字,任何以前写入的数据都将被发 送,并且后跟 TCP 的正常连接终止序列。 如果在套接字上调用 shutdownOutput() 后写入套接字输出流, 则该流将抛出 IOException。 即不能通过此套接字的输出流发送任何数据。
服务端

public static void testMany() throws Exception{
		// 1 开启服务端端口
		ServerSocket ss = new  ServerSocket(9999);
		System.out.println("服务端已启动,正在等在连接.....");
		// 2 接收客户端连接
		// 当程序执行到这里就会进入等待状态,一直到有客户端连接为止
		Socket skt = ss.accept();
		System.out.println("客户端已连接");
		// 3 调用聊天方法
		TcpManager.socket(skt);
		
	}

客户端

public static void main(String[] args) throws Exception {
		// 创建对象,指定服务端IP和端口
		Socket skt = new Socket("127.0.0.1",9999);
		System.out.println("连接成功");
		// 调用聊天方法
		TcpManager.socket(skt);

	}

业务类(多线程阻塞式交互)

public class TcpManager {
	public static void socket(Socket skt) throws Exception {
		// 获取输出流
		OutputStream os = skt.getOutputStream();
		// 转换为字符打印流
		PrintWriter out = new PrintWriter(new OutputStreamWriter(os, "utf-8"));
		// 获取输入流
		InputStream is = skt.getInputStream();
		// 转换为字符缓存流
		BufferedReader br = new BufferedReader(new InputStreamReader(is,
				"utf-8"));

		// 多线程写出数据
		Thread outThread = new Thread(new Runnable() {

			@Override
			public void run() {
				Scanner scanner = new Scanner(System.in);
				String msg = null;
				while ((msg = scanner.nextLine()) != null && !msg.equals("拜拜")) {
					out.println(msg);
					out.flush();
				}
				System.out.println("聊天结束");
			}
		});
		outThread.start();

		// 多线程读取数据
		Thread intThread = new Thread(new Runnable() {

			@Override
			public void run() {
				String msg = null;
					try {
						while ((msg = br.readLine()) != null && !msg.equals("拜拜")) {
							System.out.println(skt.getInetAddress().getHostName()
									+ " : " + msg);
						}
					} catch (IOException e) {
						e.printStackTrace();
					}
				System.out.println("聊天结束");
			}
		});
		intThread.start();

		// 线程合并,等不聊天之后,再关闭资源
			outThread.join();
			// 4 关闭流,先打开的后关闭
			br.close();
			is.close();
			out.close();
			os.close();
			skt.close();
	}
}

UDP

  • 流 程:
  1. DatagramSocket与DatagramPacket
  2. 建立发送端,接收端
  3. 建立数据包
  4. 调用Socket的发送、接收方法
  5. 关闭Socket
    发送端与接收端是两个独立的运行程序

DatagramSocket 类的常用方法
public DatagramSocket(int port)创建数据报套接字并将其绑定到本地主机上的指定端口。套接字将被绑定到通配符地址,IP 地址由内核来选择。
public DatagramSocket(int port,InetAddress laddr)创建数据报套接字,将其绑定到指定的本地地址。 本地端口必须在 0 到 65535 之间(包括两者)。如果 IP 地址为 0.0.0.0,套接字将被绑定到通配符地 址,IP 地址由内核选择。
public void close()关闭此数据报套接字。
public void send(DatagramPacket p)从此套接字发送数据报包。DatagramPacket 包含的信息指示:将要发送的数据、其长度、远程主机的 IP 地址和远程主机的端口号。
public void receive(DatagramPacket p)从此套接字接收数据报包。当此方法返回时,DatagramPacket 的缓冲区填充了接收的数据。数据报包也包含发送方的 IP 地址和发送方机器上的端口号。 此方法 在接收到数据报前一直阻塞。数据报包对象的 length 字段包含所接收信息的长度。如果信息比包的 长度长,该信息将被截短。
public InetAddress getLocalAddress()获取套接字绑定的本地地址。
public int getLocalPort()返回此套接字绑定的本地主机上的端口号。
public InetAddress getInetAddress()返回此套接字连接的地址。如果套接字未连接,则返回null。
public int getPort()返回此套接字的端口。如果套接字未连接,则返回 -1。
DatagramPacket类的常用方法
public DatagramPacket(byte[] buf,int length)构造 DatagramPacket,用来接收长
度为length 的数据包。 length 参数必须小于等于 buf.length。
public DatagramPacket(byte[] buf,int length,InetAddress address,int port)构造数 据报包,用来将长度为 length 的包发送到指定主机上的指定端口号。length 参数必须小于等于buf.length。
public InetAddress getAddress()返回某台机器的 IP 地址,此数据报将要发往该
机器或者是从该机器接收到的。
public int getPort()返回某台远程主机的端口号,此数据报将要发往该主机或 者是从该主机接收到的。
public byte[] getData()返回数据缓冲区。接收到的或将要发送的数据从缓冲区
中的偏移量 offset 处开始,持续length 长度。
public int getLength()返回将要发送或接收到的数据的长度。
服务端

public class UDPServer {
	public static void main(String[] args) throws Exception{
		// 打开UDP对象,并监听某个端口
		DatagramSocket ds = new DatagramSocket(9999);
		// 包接收器接收
		byte[] buf = new byte[1024];
		// 通过包接收器把数据保存到数组中
		DatagramPacket dp = new DatagramPacket(buf, buf.length);
		// 阻塞式接收
		while (true) {
			// 通过端口接收数据
			ds.receive(dp);
			// 把数组中的数据转换为流
			ByteArrayInputStream bais = new ByteArrayInputStream(buf);
			// 转换为数据流
			DataInputStream dis = new DataInputStream(bais);
			// 读取数据
			System.out.println(dis.readUTF());
		}
	}
}

客户端

public class UDPClient {
	public static void main(String[] args) throws Exception {
		String string = "你好吗";
		// 字节数组流
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		// 封装为数据流
		DataOutputStream dos = new DataOutputStream(baos);
		dos.writeUTF(string);
		// 转换为字节数组
		byte[] buf = baos.toByteArray();
		
		// 把转换之后的这个字节数组发送出去
		// 创建数据包,并绑定接收信息
		DatagramPacket dp = new DatagramPacket(buf, buf.length,new InetSocketAddress("127.0.0.1", 9999));
		
		// 发送,通过当前电脑的 指定端口把数据包发送出去
		DatagramSocket ds = new DatagramSocket(9998);
		ds.send(dp);
	}
}

正则表达式

  • 总览

    正则表达式 : 定义了字符串的匹配模式

    可以用来搜索,编辑或处理文本,并不仅限于某一种语言,但是每种语言中有细微的差别

    JDK1.4 推出的 java.util.regex 包,很好的支持了正则表达式

    • 常用语法 :

      \ 转移符 , 把有意义字符转换为无意义字符
      	但是java中 \ 也是转移符,所以在java中编写正则表达式的时候,需要转移符的时候需要些 两个 \\
      
  • 字符取值范围相关
    [abc] : 表示 可能是a, 也可能是b, 也可能是c (是abc中的任意一个)
    [^abc] : 表示不是a,b,c中的任何一个
    [a-zA-Z] : 表示是大小写字母 , [a-z] 小写字母 , [A-Z] 大写字母 [0-9] 数字0-9
    [a-zA-Z0-9] : 表示是数字或字母

  • 简洁表示
    . : 匹配任意字符
    \d : 表示数字 等同于[0-9]
    \D : 表示非数字 等同于 [^0-9]
    \s : 表示由空字符组成, [\t\n\r\x\f]
    \S : 表示非空字符组成
    \w : 表示由字母数字下划线组成 [a-zA-Z0-9_]
    \W : 表示非字母数字下划线 [^a-zA-Z0-9_]

  • 表示数量的
    ? : 表示出现0次或1次
    + : 表示1次或多次, 大于等于1
    * : 任意次数(0~N)
    {n} : 表示出现n次 , {2} 表示出现2次
    {n,m} : 表示出现n次到m次 , {2,5} : 表示出现2~5次
    {n,} : 表示出现n及以上 >=n

    () : 把他们看做一个整体

| 或 , a|b ,a和b都可以匹配

^ : 以什么什么打头 , 但是 用在[^xxxx] 就表示取反
$ : 以什么什么结尾
^ a[^a-z] , a1 , aA , a3, 22

  • 校验非汉字
    [^\u4e00-\u9fa5]

语法

元字符描述
\将下一个字符标记符、或一个向后引用、或一个八进制转义符。例如,“\n”匹配\n。“\n”匹配换行符。序列“\”匹配“\”而“(”则匹配“(”。即相当于多种编程语言中都有的“转义字符”的概念。
^匹配输入字符串的开始位置。如果设置了RegExp对象的属性,^也匹配“\n”或“\r”之后的位置。
$匹配输入字符串的结束位置。如果设置了RegExp对象的Multiline属\性,$也匹配“\n”或“\r”之前的位置。
*匹配前面的子表达式任意次。例如,zo*能匹配“z”,“zo”以及“zoo”。*等价于{0,}。
+匹配前面的子表达式一次或多次(大于等于1次)。例如,“zo+”能匹配“zo”以及“zoo”,但不能匹配“z”。+等价于{1,}。
?匹配前面的子表达式零次或一次。例如,“do(es)?”可以匹配“do”或“does”中的“do”。?等价于{0,1}。
{n}n是一个非负整数。匹配确定的n次。例如,“o{2}”不能匹配“Bob”中的“o”,但是能匹配“food”中的两个o。
{n,}n是一个非负整数。至少匹配n次。例如,“o{2,}”不能匹配“Bob”中的“o”,但能匹配“foooood”中的所有o。“o{1,}”等价于“o+”。“o{0,}”则等价于“o*”。
{n,m}m和n均为非负整数,其中n<=m。最少匹配n次且最多匹配m次。例如,“o{1,3}”将匹配“fooooood”中的前三个o。“o{0,1}”等价于“o?”。请注意在逗号和两个数之间不能有空格。
.点匹配除“\r\n”之外的任何单个字符。要匹配包括“\r\n”在内的任何字符,请使用像“[\s\S]”的模式。
(pattern)匹配pattern并获取这一匹配。所获取的匹配可以从产生的Matches集合得到,在VBScript中使用SubMatches集合,在JScript中则使用$0…$9属性。要匹配圆括号字符,请使用“(”或“)”。
(?:pattern)匹配pattern但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。这在使用或字符“(|)”来组合一个模式的各个部分是很有用。例如“industr(?:y|ies)”就是一个比“industry|industries”更简略的表达式。
(?=pattern)正向肯定预查,在任何匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如,“Windows(?=95|98|NT|2000)”能匹配“Windows2000”中的“Windows”,但不能匹配“Windows3.1”中的“Windows”。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。
(?!pattern)正向否定预查,在任何不匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如“Windows(?!95|98|NT|2000)”能匹配“Windows3.1”中的“Windows”,但不能匹配“Windows2000”中的“Windows”。
(?=pattern)反向肯定预查,与正向肯定预查类似,只是方向相反。例如,“(?<=95|98|NT|2000)Windows”能匹配“2000Windows”中的“Windows”,但不能匹配“3.1Windows”中的“Windows”。
(?<!pattern)反向否定预查,与正向否定预查类似,只是方向相反。例如“(?<!95|98|NT|2000)Windows”能匹配“3.1Windows”中的“Windows”,但不能匹配“2000Windows”中的“Windows”。
x | y匹配x或y。例如,“z|food”能匹配“z”或“food”或"zood"(此处请谨慎)。“(z|f)ood”则匹配“zood”或“food”。
[xyz]字符集合。匹配所包含的任意一个字符。例如,“[abc]”可以匹配“plain”中的“a”。
[^xyz]负值字符集合。匹配未包含的任意字符。例如,“[^abc]”可以匹配“plain”中的“plin”。
[a-z]字符范围。匹配指定范围内的任意字符。例如,“[a-z]”可以匹配“a”到“z”范围内的任意小写字母字符。注意:只有连字符在字符组内部时,并且出现在两个字符之间时,才能表示字符的范围; 如果出字符组的开头,则只能表示连字符本身.
[^a-z]负值字符范围。匹配任何不在指定范围内的任意字符。例如,“[^a-z]”可以匹配任何不在“a”到“z”范围内的任意字符。
\b匹配一个单词边界,也就是指单词和空格间的位置(即正则表达式的“匹配”有两种概念,一种是匹配字符,一种是匹配位置,这里的\b就是匹配位置的)。例如,“er\b”可以匹配“never”中的“er”,但不能匹配“verb”中的“er”。
\B匹配非单词边界。“er\B”能匹配“verb”中的“er”,但不能匹配“never”中的“er”。
\cx匹配由x指明的控制字符。例如,\cM匹配一个Control-M或回车符。x的值必须为A-Z或a-z之一。否则,将c视为一个原义的“c”字符。
\d匹配一个数字字符。等价于[0-9]。
\D匹配一个非数字字符。等价于[^0-9]。
\f匹配一个换页符。等价于\x0c和\cL。
\n匹配一个换行符。等价于\x0a和\cJ。
\r匹配一个回车符。等价于\x0d和\cM。
\s匹配任何不可见字符,包括空格、制表符、换页符等等。等价于[ \f\n\r\t\v]。
\S匹配任何可见字符。等价于[^ \f\n\r\t\v]。
\t匹配一个制表符。等价于\x09和\cI。
\v匹配一个垂直制表符。等价于\x0b和\cK。
\w匹配包括下划线的任何单词字符。类似但不等价于“[A-Za-z0-9_]”,这里的"单词"字符使用Unicode字符集。
\W匹配任何非单词字符。等价于“[^A-Za-z0-9_]”。
\xn匹配n,其中n为十六进制转义值。十六进制转义值必须为确定的两个数字长。例如,“\x41”匹配“A”。“\x041”则等价于“\x04&1”。正则表达式中可以使用ASCII编码。
\num匹配num,其中num是一个正整数。对所获取的匹配的引用。例如,“(.)\1”匹配两个连续的相同字符。
\n标识一个八进制转义值或一个向后引用。如果\n之前至少n个获取的子表达式,则n为向后引用。否则,如果n为八进制数字(0-7),则n为一个八进制转义值。
\nm标识一个八进制转义值或一个向后引用。如果\nm之前至少有nm个获得子表达式,则nm为向后引用。如果\nm之前至少有n个获取,则n为一个后跟文字m的向后引用。如果前面的条件都不满足,若n和m均为八进制数字(0-7),则\nm将匹配八进制转义值nm。
\nml如果n为八进制数字(0-7),且m和l均为八进制数字(0-7),则匹配八进制转义值nml。
\un匹配n,其中n是一个用四个十六进制数字表示的Unicode字符。例如,\u00A9匹配版权符号(?)。
\ < \ >匹配词(word)的开始(\ <)和结束(\ >)。例如正则表达式\ < the \ >能够匹配字符串"for the wise"中的"the",但是不能匹配字符串"otherwise"中的"the"。注意:这个元字符不是所有的软件都支持的。
\ ( \ )将 \ ( 和 \ ) 之间的表达式定义为“组”(group),并且将匹配这个表达式的字符保存到一个临时区域(一个正则表达式中最多可以保存9个),它们可以用 \1 到\9 的符号来引用。
|将两个匹配条件进行逻辑“或”(Or)运算。例如正则表达式(him
+匹配1或多个正好在它之前的那个字符。例如正则表达式9+匹配9、99、999等。注意:这个元字符不是所有的软件都支持的。
?匹配0或1个正好在它之前的那个字符。注意:这个元字符不是所有的软件都支持的。
{i} {i,j}匹配指定数目的字符,这些字符是在它之前的表达式定义的。例如正则表达式A[0-9]{3} 能够匹配字符"A"后面跟着正好3个数字字符的串,例如A123、A348等,但是不匹配A1234。而正则表达式[0-9]{4,6} 匹配连续的任意4个、5个或者6个数字
  • 练习

1 匹配整数和小数
(-)?\\d+(\\.\\d+)?

2 电话校验
\\d{11}
1[345789]\\d{9}

Pattern

Pattern : 创建正则表达式对象,能做一些基本的简单操作

  • 三大功能 :
    验证 : boolean matchers(String regex);
    拆分 : String[] split(String regex);
    替换 : String replaceAll(String regex,String replacement);
    实际操作中,有时候我们嫌麻烦,也可以直接使用String里面的一些方法,比如 替换,拆分,验证String类中也有的
public class _01_Pattern {
	public static void main(String[] args) {
		// test_01();
		test_02();
	}
	// 验证 : boolean matchers(String regex);
	public static void test_02() {
		String regex = "(-)?\\d+(\\.\\d+)?";
		String str = "2.43";
		// 全词匹配
		boolean flag = Pattern.matches(regex, str);
		System.out.println(flag);
		
		// String类中的用法,也是全词匹配
		System.out.println(str.matches(regex));
	}
	// 拆分 String[] split(String regex);
	public static void test_01(){
		String str = "1,2@3!4";
		// 创建正则表达式对象
		Pattern pattern = Pattern.compile("[^0-9]");
		String[] strArray = pattern.split(str);
		for (String string : strArray) {
			System.out.println(string);
		}
		// String的
		String[] strArray1 = str.split("[^0-9]");
		for (String string : strArray1) {
			System.out.println(string);
		}
	}
}

Matcher

构造方法也是私有的,不能随意创建,只能通过Pattern.matcher(CharSequence input)方法得到该类的实例 Matcher m = p.matcher("aaaaab");
它支持便捷强大的正则匹配操作,包括分组、多次匹配支持

  • 三大方法

Matcher.matches():对整个字符串进行匹配,只有整个字符串都匹配了才返回true
Matcher.lookingAt():对前面的字符串进行匹配,只有匹配到的字符串在最前面才返回true
Matcher.find():对字符串进行匹配,匹配到的字符串可以在任何位置

字符串匹配

public class _02_Matcher {
	public static void main(String[] args) {
		String regex = "\\d{11}";
		String tel = "a131131131112";
		// 引擎
		Pattern pattern = Pattern.compile(regex);
		// 匹配器
		Matcher matcher = pattern.matcher(tel);
		// 三种匹配模式
		// matches : 全词匹配   xxx
		// find : 任意位置均可   .*xxx.*
		// lookingAt : 从前到后    xxx.*
		
		// 全词匹配 , 等于写着 ^ 和 $
		System.out.println(matcher.matches());
		// 注意 : 一个匹配器对象(matcher) ,调用相同的方法可以连用,不建议混用
		
		matcher = pattern.matcher(tel);
		// 只要最前面的是符合条件的 就行
		System.out.println(matcher.lookingAt());
		
		matcher = pattern.matcher(tel);
		// 任意位置符合条件 就行
		System.out.println(matcher.find());
	}
}

数据提取

public class _03_Matcher_02 {
	public static void main(String[] args) {
		// 可以使用() 对匹配到的数据进行分组, 第一个() 就是第一组,第二个() 就是第二组
		// 也可以不分组,如果不分组的情况下做数据提取,就只能提取到整个匹配到的字符串
		// 分组之后 可以提取对应组的数据
		// ((.{2,3})电话号码是) 第一组
		// (.{2,3}) 第二组
		// (\\d{11}) 第三组
		String string = "张三电话号码是13113113111张三四电话号码是13113113112张三五电话号码是13113113113张四电话号码是13113113114王五电话号码是13113113115赵六电话号码是13113113333孙小黑电话号码是13113113211小红电话号码是13113113311";
		String regex = "((.{2,3})电话号码是)(\\d{11})";
		Pattern pattern = Pattern.compile(regex);
		Matcher matcher = pattern.matcher(string);

		// find 匹配任意位置,匹配到一个之后就停止
		// 如果接着调用find方法,就会接着刚停止的地方继续向后面匹配
		while (matcher.find()) {
			// 所以 结合find特性,可以和group连用,做到数据提取
			// group : 0或者无参, 获取匹配到的整个数据,1 就是第一组,2就是第二组
			// 一个小括号 就是一组
			System.out.println(matcher.group(2) + " : " + matcher.group(3));
		}
	}
}

叠词去重

public class _04_Test {
	public static void main(String[] args) {
		String str = "我我我、、、我我、、我、我要要、、、要要要、、要要、、学学学、、、、学学、、、学编编编、、编编编程、、程程";
		// 1 先把其他没用的都去掉,只留下汉字
		// \u4e00-\u9fa5 : 汉字
		str = str.replaceAll("[^\u4e00-\u9fa5]", "");
		// System.out.println(str);
		// \\1 获取前面组中的数据
		// (\\d)\\1 : 表示连续出现的数字  , 11,22,33,44,55
		//  (\\d)(a)\\1 : 表示 第一个是数字,第二个是a,第三个和第一个一样 , 1a1  , 2a2 , 3a3
		// (\\d)(a)\\2 : 表示第一个是数字,第二个是a, 第三个和第二个一样, 1aa,2aa,3aa
		String regex = "(.)(\\1+)";
		Pattern pattern = Pattern.compile(regex);
		Matcher matcher = pattern.matcher(str);
		while (matcher.find()) {
			// 我我我我我我我
			System.out.println(matcher.group());
			// 我
			System.out.println(matcher.group(1));
			// 我我我我我我
			System.out.println(matcher.group(2));
		}
		
		// 用第一组的数据,把整个匹配到的数据替换 即可
		// $1 就等于 group(1)
		str = str.replaceAll(regex, "$1");
		// 我要学编程
		System.out.println(str);
	}
}

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2021-07-25 12:00:04  更:2021-07-25 12:01:07 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 17:33:08-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码