深入理解Java中的转义字符

最近在学习《两周自制脚本语言》这本书,在词法分析的一些复杂的正则中用到了大量的转义字符’\',比如正则字符串中包含了这个部分\\\\\"你知道它是匹配什么的么?

反斜杠在字符串和正则表达式中都有特殊作用。今天让我们来深入理解一下Java中的转义字符\

先提几个问题:
  1. Java中的字符串中的\n是一个字符还是两个?
  2. Java中代码中的字符串字面量"abc",在存储的时候,字符串内容中有没有双引号?
  3. Pattern pat = Pattern.compile(“\\\\\\\\”); (双引号内有8个反斜杠),请问它可以匹配字符串中的什么内容?非得用8个反斜杠才能表达要匹配的字符串么?6个或4个可不可以?

字符串字面量

字面量两边的双引号是干嘛的

在Java代码中写出来的字符串,叫做字符串字面量,比如String name = "Jack"中的字符串Jack就是字面量形式给出来的,它在编译后的程序中会保存在字符串常量池中。保存的内容仅仅是Jack这个字符串,共4个字符,是没有两边的双引号的。两边的双引号,仅仅是代码中写的,给Java编译器看的,编译器看到代码中出现了双引号,就知道接下来的内容是字符串,所以真正的字符串内容就是Jack这四个字符。想想name.length()不就是4么。

字符串内容中有双引号怎么办

假设我有个字符串内容是"You hurt me", she said.。代码中如果将这个字符串不做处理地用双引号包裹起来就出了问题:

String str = ""You hurt me", she said.";

编译器的眼里,只有两个字符串,第一个是空字符串,第二个是, she said.。因为编译器是通过双引号来判断字符串字面量的起止位置的。

如果你想要在字符串中包含双引号,代码要这么写:

String str = "\"You hurt me\", she said.";

即在字符串内容中的双引号前加上反斜杠作为转义字符,这样编译器读取到\"的时候,就不会认为它是字符串的结束了。

字符串内容中有反斜杠怎么办

假设我们字符串的内容中也有反斜杠,比如The backslash \ is an escape character,我们也需要在反斜杠前加一个反斜杠作为转义字符:

String str = "The backslash \\ is an escape character";
多个连续的反斜杠该怎么解读

那如果字符串的内容包含了\"该怎么写的?比如字符串的内容是The \" inner string literals means a double quote,那就要写成如下的方式:

String str = "The \\\" inner string literals means a double quote";

在字符串字面量中,如果有多个反斜杠连在一起,则奇数位置(1,3,5,7…)上的反斜杠表示转义,和它后边的字符共同决定含义。那么字符串字面量中的\\\"中的第1个反斜杠表示对它后边的反斜杠的转义,第2个反斜杠就不再是转义字符了,它被它前面的转义字符给剥夺了转义的超能力。前两个反斜杠连在一起表示一个反斜杠字符,第3个反斜杠和它后面的双引号一起表示字符串内容中的双引号。

在这里插入图片描述

字符串中多个反斜杠连续起来,只有奇数位置1,3,5,7这些位置上的反斜杠具有转义的超能力,其它位置上的都被它前面的转义字符给剥夺了转义的超能力,仅仅表示反斜杠字符本身了。所以字符串中的\\\\\\\\(8个反斜杠)表示的其实是4个反斜杠字符。这4个反斜杠字符不再具有转义的能力,不会继续转义下去。

在这里插入图片描述
但是,如果这个8个反斜杠的字符串作为正则表达式的话,它的内容是4个反斜杠,这其中奇数位置的反斜杠又有了转义的能力,不过这个转义能力是正则表达式中的转义。 所以8个反斜杠的字符串作为Pattern.compile参数的话,它先是被解读为字符串,然后这个字符串又被当作正则表达式的pattern使用。4个反斜杠在正则表达式中表示的是两个连续的反斜杠。本文后边会讲解正则表达式中的转义。

字符串内容中包含换行怎么办

如果字符串中包含了换行符,那么就需要在字符串中用\n来表示换行,换行符实际上是一个字符,因为换行符是不可打印不可显示的字符,所以你没办法在代码中直接表示它,各种编程语言都规定用\n来表示换行,也就是说在程序的代码中,要用反斜杠和字母n的组合来表示换行,但是实际上它们的组合表示的是一个换行符。

/*** 一个字符,才可以用char类型*/
char c = '\n';
String lineSeparator = "\n";
System.out.println(lineSeparator.length()); // 输出1

正则表达式中的反斜杠

在正则表达式中也有反斜杠\,它也有转义的能力。比如正则表达式中的元字符表示或的关系,如果在它前面加上了反斜杠,就仅仅表示竖线了:

在这里插入图片描述

在这里插入图片描述

也就是说在正则表达式中,反斜杠字符也是有转义的超能力的。

当Java的字符串遇上正则表达式

注意:反斜杠在Java的字符串和正则表达式中都具有转义的作用,如果它们遇到一起就需要分两步骤来解读反斜杠: 第一步将它作为字符串的含义解读出来,第二步将前一步解读出来的字符串作为正则表达式的含义解读出来。

比如我想匹配字符串中的a|b,用正则表达式写的pattern就是a\|b,可是到了java中,就得写成下面的:

// 要多加一个转义,看起来貌似正则表达式本身不太一样似的
Pattern pat = Pattern.compile("a\\|b"); 

而如果正则表达式中要匹配的是反斜杠本身,就更麻烦了,在正则表达式中要用两个反斜杠才能表达反斜杠本身。而要用java的字符串来写正则表达式的pattern,反斜杠的数量还要翻倍,比如:

Pattern pat = Pattern.compile("\\\\"); // 用于匹配字符串中单个反斜杠 

现将代码中的四个反斜杠的字符串字面量解读成有两个反斜杠字符的字符串内容本身,然后将有两个反斜杠的字符串内容作为正则表达式的pattern,那么本来已经归于平凡的反斜杠在正则表达式中又一次具有了转义的能力!

在这里插入图片描述

所以说如果Java中的正则表达式要想匹配字符串中的\",要写成:

//前面4个反斜杠表示一个不具备转义能力的反斜杠字符,
//第5个反斜杠和后边的双引号表示字符串内容中的双引号
Pattern pat = Pattern.compile("\\\\\""); 

为什么Java中的正则会有转义字符满天飞,不好读懂

造成这个现象的原因,就是Java中不支持raw string这种字符串,比如有的编程语言通过三个双引号或者三个单引号来表示raw string,这样在raw string中有双引号之类的就不用再转义一下了。比如Rust中的raw string:

在这里插入图片描述

如果用Rust的正则来匹配字符串中的反斜杠本身,则简单的多:

    //用于匹配字符串中的反斜杠,注意这儿之所以还需要写两个反斜杠,是正则表达式本身就需要两个//因为在正则表达式中,反斜杠也具有转义的功能,如果用Java写,则要写4个,多一倍的反斜杠是Java字符串造成的let regex = Regex::new(r"\\").unwrap();

英文词汇:

  1. 转义字符: escape character
  2. 反斜杠(\): backslash
  3. 字符串字面量: string literals

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/121761.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

自监督学习应用

1 自监督学习 自监督学习主要是利用辅助任务(pretext)从大规模的无监督数据中挖掘自身的监督信息,通过这种构造的监督信息对网络进行训练,从而可以学习到对下游任务有价值的表征。(也就是说自监督学习的监督信息不是人…

Linux中shell的执行流控制

目录 一、for语句 1、for语句的基本格式 2、示例 二、条件语句 1、while…do语句 2、until…do语句 3、if …then语句 4、示例 三、case语句 四、expect应答语句 1、固定答案 2、将expect与bash环境结合 3、示例 五、终止语句 一、for语句 作用:为…

高可用系统架构——关于语雀宕机的思考

语雀系统崩溃了,并且经过8个多小时才恢复,估计语雀的小伙伴们已经哭晕在厕所里了。 本次稳定性故障再次给架构师敲响警钟:系统高可用一直是架构的重点,它涉及到系统的方方面面,并且是一件持续性的长期工作。 故障起因…

我们在 Linux 环境中用 C 编程时,如果对文件读写,Linux 会自动给文件加锁嘛?以及怎么加文件锁?

task1: 验证Linux不会自动给文件加锁 先说结论&#xff0c;结论是不会 我写了一个这样的程序 #include <stdio.h> #include <unistd.h>int main() {const char* pathname "your_file_pathname.txt";FILE* file NULL;int count 100;if(access(pathn…

数据可视化报表分享:区域管理驾驶舱

在零售数据分析中&#xff0c;区域管理驾驶舱报表是用来分析企业运营数据&#xff0c;以制定销售策略和提高利润。因此这张报表需要整合大量数据&#xff0c;数据整合、分析、指标计算的工作量极大&#xff0c;在讲究高效率、高度及时性的大数据时代&#xff0c;BI数据可视化分…

Linux--安装与配置虚拟机及虚拟机服务器坏境配置与连接---超详细教学

一&#xff0c;操作系统介绍 1.1.什么是操作系统 操作系统&#xff08;Operating System&#xff0c;简称OS&#xff09;是一种系统软件&#xff0c;它是计算机硬件和应用软件之间的桥梁。它管理计算机的硬件和软件资源&#xff0c;为应用程序提供接口和服务&#xff0c;并协调…

9、定义错误页

在layouts目录下新建error.vue&#xff0c;可以通过layout函数使用布局文件&#xff0c;通过props: [“error”]能拿到错误信息对象。 <template><div>{{ error.statusCode }}: {{ error.message }}</div> </template><script> export default {…

vue3 源码解析(2)— ref、toRef、toRefs、shallowRef 响应式的实现

前言 vue3 源码解析&#xff08;1&#xff09;— reactive 响应式实现 介绍完 reactive 之后还有另一个很重要的响应式API&#xff0c;其中包括 ref、toRef、toRefs 和 shallowRef。这些API在vue3中起着至关重要的作用&#xff0c;它们帮助我们更好地管理和跟踪响应式数据的变…

漏洞复现-dedecms文件上传(CVE-2019-8933)

dedecms文件上传_CVE-2019-8933 漏洞信息 Desdev DedeCMS 5.7SP2版本中存在安全漏洞CVE-2019-8933文件上传漏洞 描述 ​ Desdev DedeCMS&#xff08;织梦内容管理系统&#xff09;是中国卓卓网络&#xff08;Desdev&#xff09;公司的一套基于PHP的开源内容管理系统&#x…

【面试经典150 | 链表】合并两个有序链表

文章目录 Tag题目来源题目解读解题思路方法一&#xff1a;递归方法二&#xff1a;迭代 写在最后 Tag 【递归】【迭代】【链表】 题目来源 21. 合并两个有序链表 题目解读 合并两个有序链表。 解题思路 一种朴素的想法是将两个链表中的值存入到数组中&#xff0c;然后对数组…

轻量级仿 Spring Boot=嵌入式 Tomcat+Spring MVC

啥&#xff1f;Spring Boot 不用&#xff1f;——对。就只是使用 Spring MVC Embedded Tomcat&#xff0c;而不用 Boot。为啥&#xff1f;——因为 Boot 太重了&#xff1a;&#xff09; 那是反智吗&#xff1f;Spring Boot 好好的就只是因为太重就不用&#xff1f;——稍安勿…

有一个带头结点的单链表L,设计一个算法使其元素递增有序

有一个带头结点的单链表L&#xff0c;设计一个算法使其元素递增有序 代码思路&#xff1a; 我这里懒得搞那个指针了&#xff0c;直接遍历一遍链表&#xff0c;把链表的元素复制到数组arr里面 对数组A进行一下排序&#xff0c;排完之后再把元素复制到L里面。 至于排序你用啥算…

运维 | 使用 Docker 安装 Jenkins | Jenkins

运维 | 使用 Docker 安装 Jenkins | Jenkins 前言 本期内容主要是为了学习如何通过 Docker 安装Jenkins&#xff0c;仅作为记录与参考&#xff0c;希望对大家有所帮助。 准备工作 系统&#xff1a;CentOS 7.9配置&#xff1a;4c8g 快速安装 下面以 Docker 方式安装 Jenkin…

第2篇 机器学习基础 —(2)分类和回归

前言&#xff1a;Hello大家好&#xff0c;我是小哥谈。机器学习中的分类和回归都是监督学习的问题。分类问题的目标是将输入数据分为不同的类别&#xff0c;而回归问题的目标是预测一个连续的数值。分类问题输出的是物体所属的类别&#xff0c;而回归问题输出的是数值。本节课就…

【Matlab2016】Matlab中文版的下载、安装、激活(不建议安装过高版本!!)

这里写目录标题 首先双击R2016_win64.iso加载镜像文件双击setup.exe开始安装选择使用文件密钥安装填入密钥修改安装路径并记住此路径建议全部勾选等待安装完成 激活复制补丁到matlab路径下 创建快捷方式进入bin目录&#xff0c;找到matlab.exe 安装包 首先双击R2016_win64.iso加…

网络搭建和运维的基础题目

服务部分&#xff08;linux&#xff09; 实操部分 1.在任意文件夹下面创建形如 A/B/C/D 格式的文件夹系列。 [rootlocalhost ~]# mkdir -p A/B/C/D 2.在创建好的文件夹下面&#xff0c;A/B/C/D &#xff0c;里面创建文本文件 mkdir.txt [rootlocalhost ~]# cd A/B/C/D [r…

[17]JAVAEE-HTTP协议

目录 一、什么是HTTP协议 什么时候会用到HTTP协议&#xff1f; HTTP协议的工作流程 二、HTTP的报文格式 抓包 HTTP请求报文格式 1.首行 2.header 常见键值对&#xff1a; 3.空行 4.正文&#xff08;body&#xff09;&#xff08;有的时候可以没有&#xff09; HTTP…

ubuntu下Docker的简单使用并利用主机显示

首先分享一个docker镜像的网站&#xff1a;https://hub.docker.com/search?q 这个网站里面有很多配置好的镜像&#xff0c;可以直接拉取。 下面介绍一下docker的安装和使用。 1、docker得到安装&#xff1a; sudo apt-get install docker 2、docker拉取一个镜像到本地,这里我…

Python爬虫防止被封的方法:动态代理ip

目录 前言 一、为什么需要使用动态IP代理 1.网站反爬虫机制 2.突破本地IP限制 3.获取更多数据 二、Python爬虫动态IP代理的实现方法 1.使用第三方库 2.使用爬虫框架 三、预防被封的方法 1.代理池管理 2.请求间隔设置 3.使用多个代理 总结 前言 在进行网站爬取时&…

网络基础-3

路由开销 一条路由的开销时指到达这条路由的目的地/掩码需要付出的带价值。同一种路由协议发现有多条路由可以到达同一目的地/掩码时&#xff0c;将优选开销最小的路由&#xff0c;即只把开销最小的路由加入进本协议的路由表中。 路由协议 内部网关协议&#xff08;IGP&…