有没有办法在 Java 中使用原始字符串(没有转义序列)?
(我正在编写大量的正则表达式代码,原始字符串会使我的代码更具可读性)
我知道该语言并没有直接提供这一点,但是有没有办法以任何方式“模拟”它们?
如果您使用的是 eclipse,这是一种解决方法。当您将文本粘贴到字符串文字中时,您可以自动使长文本块正确地多行并自动转义特殊字符
"-粘贴在这里-";
如果您在窗口→首选项→java→编辑器→键入→“粘贴到字符串文字时转义文本”中启用该选项
不,没有。
通常,您会将原始字符串和正则表达式放在属性文件中,但它们也有一些转义序列要求。
我使用Pattern.quote。它解决了问题的问题。因此:
Pattern pattern = Pattern.compile(Pattern.quote("\r\n?|\n"));
quote 方法返回一个与提供的字符串参数匹配的字符串,返回字符串是我们案例中正确引用的字符串。
不(很遗憾)。
是的。
文本块来到 Java
一些历史: 原始字符串文字被撤回。这原本是 JDK 12 中的一个预览语言功能,但它被撤回并且没有出现在 JDK 12 中。 它在 JDK 13 中被 Text Blocks (JEP 355) 取代。
您可以使用文本块轻松定义多行字符串文字。您不需要添加常规字符串文字附带的视觉混乱:连接运算符和转义序列。您还可以控制字符串值的格式。例如,让我们看一下下面的 HTML 片段:
String html = """
<HTML>
<BODY>
<H1>"Java 13 is here!"</H1>
</BODY>
</HTML>""";
请注意分隔块的开头和结尾的三个引号。
将原始文本文件放在您的类路径中并使用 getResourceAsStream(....) 读取它
(属性文件很常见,但很混乱 - 我将大多数正则表达式视为代码,并将其保存在我可以参考的地方,你也应该这样做。至于实际问题:)
是的,有一些方法可以解决可读性差的问题。你可以试试:
String s = "crazy escaped garbage"; //readable version//
虽然这在更新时需要小心。Eclipse 有一个选项可以让您在引号之间粘贴文本,并为您应用转义序列。策略是先编辑可读版本,然后删除垃圾,并将它们粘贴在空引号“”之间。
构思时间:
破解你的编辑器来转换它们;作为插件发布。我检查了插件,但没有找到(尝试搜索)。转义的源字符串和文本框文本之间存在一对一的对应关系(折扣 \n,\r\n)。也许可以使用两端带有两个引号的突出显示文本。
String s = "##########
#####";
其中 # 是突出显示的任何字符 - 中断被视为换行符。在突出显示区域内键入或粘贴的文本在“真实”源中转义,并显示为好像不是。(与 Eclipse 转义粘贴文本的方式相同,这将转义键入的文本,并在不带反斜杠的情况下显示它。)如果要正常编辑,请删除其中一个引号会导致语法错误。唔。
注意:截至今天,不可用。每当功能发布时,我可能会再次编辑此答案。
有一个在 Java 中引入原始字符串的提议。它们实际上在正则表达式的情况下非常有用。
示例 1:编码为的正则表达式字符串
System.out.println("this".matches("\\w\\w\\w\\w"));
可以交替编码为
System.out.println("this".matches(`\w\w\w\w`));
因为反斜杠不被解释为具有特殊含义。
示例 2:附加外语的多行字符串文字。
A multiple line string that was coded as
String html = "<html>\n" +
" <body>\n" +
" <p>Hello World.</p>\n" +
" </body>\n" +
"</html>\n";
可以交替编码为
String html = `<html>
<body>
<p>Hello World.</p>
</body>
</html>
`;
这避免了对中间引号、连接和显式换行的需要。
希望我们可以期待很快发布。
String#getBytes()公开了包含在每个 String 对象中的内部字节数组的副本,该对象实际上包含 16 位 UTF-16 编码的字符串 - 字节数组将包含转换为匹配平台默认字符集的相同字符串。我要说的是,我认为这与 Java 中的“原始”字符串一样接近。
您可以编写自己的非转义属性阅读器并将字符串放入资源文件中。
我个人认为正则表达式字符串数据而不是代码,所以我不喜欢在我的代码中使用它们——但我意识到这是不切实际且不受欢迎的(是的,我意识到,你不必对我大喊大叫)。
鉴于没有本地方法可以做到这一点,我可以提出两种可能性(嗯,三种,但第三种是,嗯,不自然)。
所以我个人的偏好是将文件解析为字符串。您可以命名文件中的每个条目并将它们全部加载到哈希表中,以便从代码中轻松访问。
第二种选择,创建一个会被预处理成java接口的文件;它可以逃避正则表达式。就我个人而言,我讨厌代码生成,但如果 java 文件 100% 从未被人工编辑过,那也不算太糟糕(真正的邪恶是生成的文件需要你编辑!)
第三(棘手而且可能是个坏主意):您可以创建一个自定义 doclet,在编译时将字符串从注释中提取到文本文件或头文件中,然后使用上述其他两种方法之一。这会将您的字符串保存在使用它们的同一文件中。这可能真的很难正确地做到,而且失败的惩罚是极端的,所以我什至不会考虑它,除非我有压倒性的需求和一些令人印象深刻的才能。
我只建议这样做,因为注释是自由格式的,并且“pre”标签中的内容对于格式化程序和其他系统丑陋非常安全。doclet 可以在打印 javadocs 之前提取它,甚至可以添加一些生成的 javadocs 以指示您使用正则表达式字符串。
在否决并告诉我这是一个愚蠢的想法之前 - 我知道,我只是想我会建议它,因为它很有趣,但我上面所说的偏好是一个简单的文本文件......
不,但是有一个 IntelliJ 插件可以让这更容易处理,称为String Manipulation。
IntelliJ 还将自动转义粘贴到其中的字符串。(正如@Dread指出的那样,Eclipse 有一个插件可以实现这一点。)
该问题要求提供类似于原始字符串的东西,专门用于支持正则表达式,它通常具有类似于转义字符的部分。因此,例如,\d
表示正则表达式中的数字,并且需要写入\\d
Java 字符串。同时,正则表达式中的斜线文字将像\\
在 Java 中那样编写,\\\\
这使得代码难以阅读。
关于 Java 中提议的原始字符串的答案是最有希望的,但遗憾的是该提议未被接受。关于 Pattern.quote() 的答案适用于某些存在重叠的字符串,但不会处理像 \d 和 \w 这样的情况,它们首先不是有效的 Java 字符串。关于多行字符串的答案对于大多数困扰原始提问者的复杂正则表达式字符串也无济于事,他们正在寻找更干净的 Java 正则表达式代码。
因此,我的回答是以下尴尬。反斜杠在 Unicode 中称为 Reverse Solidus。(正斜杠是常规的斜线。)Unicode 有几个看起来像的替代方案,尤其是在某些代码编辑器(例如 IntelliJ IDEA)中。这些包括大反向固相线、小反向固相线和 Set Minus。因此,引导 Pattern.quote() 答案,我们使用 Big Reverse Solidus 等替代方法编写正则表达式,并在使用它时对转义的常规反斜杠执行字符串替换。正则表达式的其他方面不太可能需要 Big Reverse Solidus。
因此,我们可以写:
Pattern pattern = Pattern.compile("∖d+".replace('∖', '\\'));
您甚至可以将字符串替换写入类似于 Pattern.quote() 的静态方法,以获得更好看的代码。