深入理解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.rhkb.cn/news/172171.html

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

相关文章

数据分享 I 地级市人口和土地使用面积基本情况

数据地址: 地级市人口和土地使用面积基本情况https://www.xcitybox.com/datamarketview/#/Productpage?id394 基本信息. 数据名称: 地级市人口和土地使用面积基本情况 数据格式: ShpExcel 数据时间: 2021年 数据几何类型: 面 数据坐标系: WGS84坐标系 数据…

【计算机毕设经典案例】基于微信小程序的图书管理系统

前言:我是IT源码社,从事计算机开发行业数年,专注Java领域,专业提供程序设计开发、源码分享、技术指导讲解、定制和毕业设计服务 👉IT源码社-SpringBoot优质案例推荐👈 👉IT源码社-小程序优质案例…

『力扣刷题本』:移除链表元素

一、题目 给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val val 的节点,并返回 新的头节点 。 示例 1: 输入:head [1,2,6,3,4,5,6], val 6 输出:[1,2,3,4,5]示例 2: 输入&a…

在spring boot+vue项目中@CrossOrigin 配置了允许跨域但是依然报错跨域,解决跨域请求的一次残酷经历

首先,说一下我们的项目情况,我们项目中后端有一个过滤器,如果必须要登录的接口路径会被拦下来检查,前端要传一个token,然后后端根据这个token来判断redis中这个用户是否已经登录。 if (request.getMethod().equals(&qu…

css 三栏布局的实现?

目录 前言 用法 代码 理解 高质量图片 1. 左侧栏 - 导航菜单 2. 中间栏 - 主要内容 3. 右侧栏 - 小部件和广告 布局的响应式设计 三栏布局在前端页面设计中是一个常见的布局方式,通常包含左侧、中间和右侧三个部分。这种布局方式在多种场景中都很受欢迎&am…

解决Windows出现找不到mfcm90u.dll无法打开软件程序的方法

今天,我非常荣幸能够在这里与大家分享关于mfc90u.dll丢失的5种解决方法。在我们日常使用电脑的过程中,可能会遇到一些软件或系统错误,其中之一就是mfc90u.dll丢失。那么,mfc90u.dll究竟是什么文件呢?接下来&#xff0c…

【表面缺陷检测】钢轨表面缺陷检测数据集介绍(2类,含xml标签文件)

一、介绍 钢轨表面缺陷检测是指通过使用各种技术手段和设备,对钢轨表面进行检查和测量,以确定是否存在裂纹、掉块、剥离、锈蚀等缺陷的过程。这些缺陷可能会对铁路运输的安全和稳定性产生影响,因此及时进行检测和修复非常重要。钢轨表面缺陷…

spring boot利用redis作为缓存

一、缓存介绍 在 Spring Boot 中,可以使用 Spring Cache abstraction 来实现缓存功能。Spring Cache abstraction 是 Spring 框架提供的一个抽象层,它对底层缓存实现(如 Redis、Ehcache、Caffeine 等)进行了封装,使得在…

微服务-Feign

文章目录 Feign介绍Feign的基本使用自定义Feign的配置Feign性能优化Feign最佳实践 Feign介绍 RestTemplate远程调用存在的问题:代码可读性差,java代码中夹杂url;参数复杂很难维护 String url "http://userservice/user/" order.g…

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

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

1820_ChibiOS中的同步消息

全部学习汇总: GreyZhang/g_ChibiOS: I found a new RTOS called ChibiOS and it seems interesting! (github.com) 1. 看到这里提到的这个模型,我在想是不是我一直没有搞定的多核可以利用这个机制来解决。如果是多核,ChibiOS的这种机制是否依…

【java学习—十】捕获异常(2)

文章目录 1. 什么是异常2. 异常处理机制3. 捕获异常总结3.1. try 和 catch3.2. 捕获异常的有关信息:3.3. finally 1. 什么是异常 如果程序运行时,某一行出现异常,将会使程序中断,不在继续执行,举个例子如下&#xff1…

二进制部署kubernetes集群的推荐方式

软件版本: 软件版本containerdv1.6.5etcdv3.5.0kubernetesv1.24.0 一、系统环境 1.1 环境准备 角色IP服务k8s-master01192.168.10.10etcd、containerd、kube-apiserver、kube-scheduler、kube-controller-manager、kubele、kube-proxyk8s-node01后续etcd、conta…

ARM 汇编指令 orreq 的使用

orreq 阅读代码时,发现有个【组合指令】 orreq, orr 一般是 OR,也就是或操作,后面加个 eq 表示什么呢? 比如下面的代码:前面一个操作, tst,好像没做实际的操作,可能影响…

[AutoSAR系列] 1.3 AutoSar 架构

依AutoSAR及经验辛苦整理,原创保护,禁止转载。 专栏 《深入浅出AutoSAR》 1. 整体架构 ​ 图片来源: AutoSar 官网 从官往图中可以看出autosar作为汽车ECU软件架构,是通过分层来实现软硬件隔离。就像大多数操作系统一样&#xff…

Docker swarm集群之compose启动多服务

Docker swarm集群之compose启动多服务 本篇文章是在搭建过Swarm集群基础上进行的,如未搭建过请移步 : [Docker swarm 集群搭建 - Wanwan’s Blog (wanwancloud.cn)] 环境信息 主机名IP主机配置master10.10.10.32c2gnode0110.10.10.42c2gnode0210.10.…

项目中拖拽元素,可以使用html的draggable属性,当然也可以用第三方插件interact

项目中拖拽元素&#xff0c;可以使用html的draggable属性&#xff0c;当然也可以用第三方插件interact 一、安装二、引用三、使用 一、安装 npm install interactjs二、引用 import interact from interactjs三、使用 <div class"drag_box"> &…

DevOps持续集成-Jenkins(1)

文章目录 DevOpsDevOps概述Code阶段工具&#xff08;centos7-gitlab主机&#xff09;Windows下安装Git&#xff08;作用是&#xff1a;使我们可以上传代码到GitLab&#xff09;Linux下安装GitLab⭐&#xff08;作用是&#xff1a;运行一个GitLab接收代码&#xff09;环境准备先…

【axios】axios的基本使用

一、 Axios简介 1、 Axios是什么&#xff1f; Axios是一个基于promise的HTTP库&#xff0c;类似于jQuery的ajax&#xff0c;用于http请求。可以应用于浏览器端和node.js&#xff0c;既可以用于客户端&#xff0c;也可以用于node.js编写的服务端。 2.、Axios特性 支持Promis…

一文讲明:企业知识库的作用和搭建方法

在现代商务环境中&#xff0c;企业面临着大量的信息和知识流动。这些信息和知识散落在各个部门、团队甚至个人之间&#xff0c;难以进行有效的整合和利用。而企业知识库的出现解决了这一问题。它提供了一个统一的平台&#xff0c;将分散的信息汇聚到一个集中的数据库中&#xf…