刨根问底:Java中的“\p{P}”到底是什么意思

2023-12-04 02:10

本文主要是介绍刨根问底:Java中的“\p{P}”到底是什么意思,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

问题由来:
在代码中看到了Pattern.compile("\\p{P}"),用来识别符号,但是这个正则表达式却不匹配加号+,所以\p{P}到底是什么意思呢

谷歌了一下,找到StackOverflow上有人问了一模一样的问题

可是这个问题被关掉了,理由是问题重复,贴出了另一个解释所有正则表达式含义的参考回答

nice try,给出正则表达式的参考回答,此举可以减少重复零散的提问
问题是这个参考回答里面根本没有说\p{P}到底是什么意思
(似乎在查正则表达式的时候总会遇到类似的问题,然后每次都会归因于自己没学好正则)
在这里插入图片描述
再回去看StackOverflow上的回答,有人贴出了Java文档,说这篇文档中有解释

问题是,并没有啊

在这里插入图片描述

文档中提到了\p{Punct},是下列符号之一:!"#$%&'()*+,-./:;<=>?@[]^_`{|}~,很好,定义非常清晰。

\p{P}会是\p{Punct}的缩写吗,可是\p{P}是不会匹配+的,而\p{Punct}的定义中是包含+
文档中还提到了\p{Print},是可打印字符[\p{Graph}\x20],其中\p{Graph}[\p{Alnum}\p{Punct}],其中[\p{Lower}\p{Upper}],其中\p{Lower}\p{Upper}分别是[a-z][A-Z]。好家伙,环环相扣。
所以\p{P}\p{Punct}还是\p{Print}呢,反正Java文档里面没说。

测试一下

Pattern.matches("\\p{P}", "+");
Pattern.matches("\\p{Punct}", "+");

结果分别是falsetrue,显然\p{P}\p{Punct}不是一回事

再回到StackOverflow,在Java文档的回复下还有两条回复

If I search the Javadocs I don’t find \p{P} just \p{Punctuation} and \p{Print}. Similarly I searched the referenced answer which is already supposed to answer this question and also don’t find a reference to \p{P}

我查找了Java文档,没找到\p{P},只找到\p{Punctuation}\p{Print}。同样,我查找了参考回答,那里面本应有这个问题的答案吧?但是我没找到对于\p{P}的解释

The linked question (“What does this regex mean?”) doesn’t specifically mention the punctuation Unicode category, but does state that \p is for Unicode categories, which addresses what \p means (which is asked in this question). Whether it’s a duplicate depends in part on whether this question is primarily asking for an explanation for \p, or what the ‘P’ category is (in which case, this question is actually asking 2 questions, one of which is a duplicate).

链接中的问题(“这个正则表达式是什么意思”)并未明确提及Unicode的标点目录,不过确实说到了\p表示Unicode目录,这解决了\p是什么意思的问题(这是本问题中问到的)。这个问题是否重复部分取决于这个问题首先是要求解释\p,还是要求解释“P目录”是什么(在这种情况下,这个问题实际上是提出了两个问题,其中一个是重复的)。

看来不止我有同样的疑问。
再看这个问题的关闭记录,里面提到StackOverflow社区重新审核了是否要重新开启这个问题,结论是,还是让它保持关闭状态吧,当初关闭它的理由不变。怎么就感觉这个问题这么冤呢?

这时我还发现idea居然能识别\p{P}\p{Punct}
(这个提示也说明\p{P}不是\p{Print}
在这里插入图片描述
在这里插入图片描述
得,Punctuation和Punctuation characters还有区别

既然谁讲也讲不清楚,那就暴力试验一下,\p{P}\p{Punct}到底会匹配哪些字符

    public static final Pattern P = Pattern.compile("\\p{P}");public static final Pattern PUNCT = Pattern.compile("\\p{Punct}");public static void main(String[] args) {StringBuilder psb = new StringBuilder();StringBuilder punctsb = new StringBuilder();// 穷举所有码点for (int i = Character.MIN_CODE_POINT; i < Character.MAX_CODE_POINT; i++) {String c = String.valueOf(Character.toChars(i));if (P.matcher(c).find()) {psb.append(c);}if (PUNCT.matcher(c).find()) {punctsb.append(c);}}System.out.println(psb);System.out.println(punctsb);}

输出结果如下,说来差别也是蛮大的

!"#%&'()*,-./:;?@[\]_{}¡§«¶·»¿;·՚՛՜՝՞՟։֊־׀׃׆׳״؉؊،؍؛؞؟٪٫٬٭۔܀܁܂܃܄܅܆܇܈܉܊܋܌܍߷߸߹࠰࠱࠲࠳࠴࠵࠶࠷࠸࠹࠺࠻࠼࠽࠾࡞।॥॰૰෴๏๚๛༄༅༆༇༈༉༊་༌།༎༏༐༑༒༔༺༻༼༽྅࿐࿑࿒࿓࿔࿙࿚၊။၌၍၎၏჻፠፡።፣፤፥፦፧፨᐀᙭᙮᚛᚜᛫᛬᛭᜵᜶។៕៖៘៙៚᠀᠁᠂᠃᠄᠅᠆᠇᠈᠉᠊᥄᥅᨞᨟᪠᪡᪢᪣᪤᪥᪦᪨᪩᪪᪫᪬᪭᭚᭛᭜᭝᭞᭟᭠᯼᯽᯾᯿᰻᰼᰽᰾᰿᱾᱿᳀᳁᳂᳃᳄᳅᳆᳇᳓‐‑‒–—―‖‗‘’‚‛“”„‟†‡•‣․‥…‧‰‱′″‴‵‶‷‸‹›※‼‽‾‿⁀⁁⁂⁃⁅⁆⁇⁈⁉⁊⁋⁌⁍⁎⁏⁐⁑⁓⁔⁕⁖⁗⁘⁙⁚⁛⁜⁝⁞⁽⁾₍₎〈〉❨❩❪❫❬❭❮❯❰❱❲❳❴❵⟅⟆⟦⟧⟨⟩⟪⟫⟬⟭⟮⟯⦃⦄⦅⦆⦇⦈⦉⦊⦋⦌⦍⦎⦏⦐⦑⦒⦓⦔⦕⦖⦗⦘⧘⧙⧚⧛⧼⧽⳹⳺⳻⳼⳾⳿⵰⸀⸁⸂⸃⸄⸅⸆⸇⸈⸉⸊⸋⸌⸍⸎⸏⸐⸑⸒⸓⸔⸕⸖⸗⸘⸙⸚⸛⸜⸝⸞⸟⸠⸡⸢⸣⸤⸥⸦⸧⸨⸩⸪⸫⸬⸭⸮⸰⸱⸲⸳⸴⸵⸶⸷⸸⸹⸺⸻、。〃〈〉《》「」『』【】〔〕〖〗〘〙〚〛〜〝〞〟〰〽゠・꓾꓿꘍꘎꘏꙳꙾꛲꛳꛴꛵꛶꛷꡴꡵꡶꡷꣎꣏꣸꣹꣺꤮꤯꥟꧁꧂꧃꧄꧅꧆꧇꧈꧉꧊꧋꧌꧍꧞꧟꩜꩝꩞꩟꫞꫟꫰꫱꯫﴾﴿︐︑︒︓︔︕︖︗︘︙︰︱︲︳︴︵︶︷︸︹︺︻︼︽︾︿﹀﹁﹂﹃﹄﹅﹆﹇﹈﹉﹊﹋﹌﹍﹎﹏﹐﹑﹒﹔﹕﹖﹗﹘﹙﹚﹛﹜﹝﹞﹟﹠﹡﹣﹨﹪﹫!"#%&'()*,-./:;?@[\]_{}⦅⦆。「」、・𐄀𐄁𐄂𐎟𐏐𐡗𐤟𐤿𐩐𐩑𐩒𐩓𐩔𐩕𐩖𐩗𐩘𐩿𐬹𐬺𐬻𐬼𐬽𐬾𐬿𑁇𑁈𑁉𑁊𑁋𑁌𑁍𑂻𑂼𑂾𑂿𑃀𑃁𑅀𑅁𑅂𑅃𑇅𑇆𑇇𑇈𒑰𒑱𒑲𒑳
!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~

idea还有自动补全提示
在这里插入图片描述
这么看来Unicode确实有很多用字母或缩写表示的category,理应是存在一个文档的,不然idea怎么认识呢,不然Java怎么会去实现呢

或许关键词是Unicode category
回到StackOverflow的参考回答,在其中找到了一个叫Unicode categories的链接,链接到了另一个问题:Unicode category L是什么
其中一个回答贴出了一个链接,其中列出了所有的Unicode categories

谷歌一下Unicode categories,找到了维基百科的解释

这些名字越看越眼熟,不就是我两年前看过的东西么,淦

总结一下
\p{P}是Unicode定义的,是一个Unicode目录,表示所有的符号,可以细分为Pc、Pd、Pe等等
\p{Punct}是Java定义的,是下列符号之一:!"#$%&'()*+,-./:;<=>?@[]^_`{|}~

那么还有最后一个问题
为什么Unicode P目录下不包含加号+

其实也没有为什么,反正Unicode把加号归类到S目录下了(S for Symbol),具体来说是Sm目录(Symbol, math)

刨根问底结束

这篇关于刨根问底:Java中的“\p{P}”到底是什么意思的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/451718

相关文章

Java实现检查多个时间段是否有重合

《Java实现检查多个时间段是否有重合》这篇文章主要为大家详细介绍了如何使用Java实现检查多个时间段是否有重合,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录流程概述步骤详解China编程步骤1:定义时间段类步骤2:添加时间段步骤3:检查时间段是否有重合步骤4:输出结果示例代码结语作

Java中String字符串使用避坑指南

《Java中String字符串使用避坑指南》Java中的String字符串是我们日常编程中用得最多的类之一,看似简单的String使用,却隐藏着不少“坑”,如果不注意,可能会导致性能问题、意外的错误容... 目录8个避坑点如下:1. 字符串的不可变性:每次修改都创建新对象2. 使用 == 比较字符串,陷阱满

Java判断多个时间段是否重合的方法小结

《Java判断多个时间段是否重合的方法小结》这篇文章主要为大家详细介绍了Java中判断多个时间段是否重合的方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录判断多个时间段是否有间隔判断时间段集合是否与某时间段重合判断多个时间段是否有间隔实体类内容public class D

IDEA编译报错“java: 常量字符串过长”的原因及解决方法

《IDEA编译报错“java:常量字符串过长”的原因及解决方法》今天在开发过程中,由于尝试将一个文件的Base64字符串设置为常量,结果导致IDEA编译的时候出现了如下报错java:常量字符串过长,... 目录一、问题描述二、问题原因2.1 理论角度2.2 源码角度三、解决方案解决方案①:StringBui

Java覆盖第三方jar包中的某一个类的实现方法

《Java覆盖第三方jar包中的某一个类的实现方法》在我们日常的开发中,经常需要使用第三方的jar包,有时候我们会发现第三方的jar包中的某一个类有问题,或者我们需要定制化修改其中的逻辑,那么应该如何... 目录一、需求描述二、示例描述三、操作步骤四、验证结果五、实现原理一、需求描述需求描述如下:需要在

Java中ArrayList和LinkedList有什么区别举例详解

《Java中ArrayList和LinkedList有什么区别举例详解》:本文主要介绍Java中ArrayList和LinkedList区别的相关资料,包括数据结构特性、核心操作性能、内存与GC影... 目录一、底层数据结构二、核心操作性能对比三、内存与 GC 影响四、扩容机制五、线程安全与并发方案六、工程

JavaScript中的reduce方法执行过程、使用场景及进阶用法

《JavaScript中的reduce方法执行过程、使用场景及进阶用法》:本文主要介绍JavaScript中的reduce方法执行过程、使用场景及进阶用法的相关资料,reduce是JavaScri... 目录1. 什么是reduce2. reduce语法2.1 语法2.2 参数说明3. reduce执行过程

如何使用Java实现请求deepseek

《如何使用Java实现请求deepseek》这篇文章主要为大家详细介绍了如何使用Java实现请求deepseek功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1.deepseek的api创建2.Java实现请求deepseek2.1 pom文件2.2 json转化文件2.2

Java调用DeepSeek API的最佳实践及详细代码示例

《Java调用DeepSeekAPI的最佳实践及详细代码示例》:本文主要介绍如何使用Java调用DeepSeekAPI,包括获取API密钥、添加HTTP客户端依赖、创建HTTP请求、处理响应、... 目录1. 获取API密钥2. 添加HTTP客户端依赖3. 创建HTTP请求4. 处理响应5. 错误处理6.

Spring AI集成DeepSeek的详细步骤

《SpringAI集成DeepSeek的详细步骤》DeepSeek作为一款卓越的国产AI模型,越来越多的公司考虑在自己的应用中集成,对于Java应用来说,我们可以借助SpringAI集成DeepSe... 目录DeepSeek 介绍Spring AI 是什么?1、环境准备2、构建项目2.1、pom依赖2.2