用于匹配不同 Unicode 脚本之间边界的正则表达式

2023-11-24

正则表达式引擎有一个“零宽度”匹配的概念,其中一些对于查找单词的边缘很有用:

  • \b- 存在于大多数引擎中,以匹配单词和非单词字符之间的任何边界
  • \< and \>- 存在于 Vim 中分别仅匹配单词开头和结尾的边界。

一些正则表达式引擎中的一个较新的概念是 Unicode 类。其中一个类是 script,它可以区分拉丁文、希腊文、西里尔文等。这些示例都是等效的,并且匹配希腊书写系统的任何字符:

  • \p{greek}
  • \p{script=greek}
  • \p{script:greek}
  • [:script=greek:]
  • [:script:greek:]

但到目前为止,在我阅读有关正则表达式和 Unicode 的资料时,我还无法确定是否有任何标准或非标准方法来实现一个脚本结束而另一个脚本开始的零宽度匹配。

在字符串中παν語之间将会有一场比赛ν and 字符,就像\b and \<将在之前匹配π特点。

现在,对于这个例子,我可以根据寻找来将一些东西组合在一起\p{Greek}其次是\p{Han},我什至可以根据两个 Unicode 脚本名称的所有可能组合来将某些东西组合在一起。

但这不是一个确定性的解决方案,因为每个版本都会将新脚本添加到 Unicode 中。有没有一种面向未来的方式来表达这一点?或者有建议添加吗?


EDIT:我只是注意到你实际上并没有具体说明which您正在使用的模式匹配语言。好吧,我希望 Perl 解决方案适合您,因为所需的机制对于任何其他语言来说可能都非常困难。另外,如果您正在使用 Unicode 进行模式匹配,Perl 确实是适合该特定类型工作的最佳选择。


当。。。的时候$rx下面的变量被设置为适当的模式,Perl 代码的这个小片段:

my $data = "foo1 and Πππ 語語語 done";

while ($data =~ /($rx)/g) {
   print "Got string: '$1'\n"; 
} 

生成此输出:

Got string: 'foo1 and '
Got string: 'Πππ '
Got string: '語語語 '
Got string: 'done'

也就是说,它会拉出一个拉丁字符串、一个希腊字符串、一个汉字字符串和另一个拉丁字符串。这与我认为你真正需要的东西非常接近。

我昨天没有发布这个的原因是我得到了奇怪的核心转储。现在我知道为什么了。

我的解决方案在 a 内部使用词汇变量(??{...})构造。事实证明,这在 v5.17.1 之前是不稳定的,最多只是偶然起作用。它在 v5.17.0 上失败,但在 v5.18.0 RC0 和 RC2 上成功。所以我添加了一个use v5.17.1确保您正在运行足够新的东西以信任这种方法。

首先,我认为您实际上并不想要运行所有相同的脚本类型;您想要运行所有相同的脚本类型plus共同的和继承的。否则,您将因 Common 的标点符号、空格和数字以及 Inherited 的组合字符而变得混乱。我真的不认为你希望这些中断你运行“所有相同的脚本”,但如果你这样做,很容易停止考虑这些。

因此,我们要做的是向前查找脚本类型不是 Common 或 Inherited 的第一个角色。更重要的是,我们从中提取脚本类型的实际内容,并使用此信息构建一个新模式,该模式是任意数量的字符,其脚本类型可以是“通用”、“继承”或我们刚刚找到并保存的任何脚本类型。然后我们评估新模式并继续。

Hey, I said它是毛茸茸的,不是吗?

在我即将展示的程序中,我留下了一些注释掉的调试语句,这些语句显示了它正在做什么。如果取消注释它们,您将获得上次运行的输出,这应该有助于理解该方法:

DEBUG: Got peekahead character f, U+0066
DEBUG: Scriptname is Latin
DEBUG: string to re-interpolate as regex is q{[\p{Script=Common}\p{Script=Inherited}\p{Script=Latin}]*}
Got string: 'foo1 and '
DEBUG: Got peekahead character Π, U+03a0
DEBUG: Scriptname is Greek
DEBUG: string to re-interpolate as regex is q{[\p{Script=Common}\p{Script=Inherited}\p{Script=Greek}]*}
Got string: 'Πππ '
DEBUG: Got peekahead character 語, U+8a9e
DEBUG: Scriptname is Han
DEBUG: string to re-interpolate as regex is q{[\p{Script=Common}\p{Script=Inherited}\p{Script=Han}]*}
Got string: '語語語 '
DEBUG: Got peekahead character d, U+0064
DEBUG: Scriptname is Latin
DEBUG: string to re-interpolate as regex is q{[\p{Script=Common}\p{Script=Inherited}\p{Script=Latin}]*}
Got string: 'done'

最后是最棘手的事情:

use v5.17.1;
use strict;
use warnings;
use warnings FATAL => "utf8";
use open qw(:std :utf8);
use utf8;

use Unicode::UCD qw(charscript);

# regex to match a string that's all of the
# same Script=XXX type
#
my $rx = qr{
    (?=
       [\p{Script=Common}\p{Script=Inherited}] *
        (?<CAPTURE>
            [^\p{Script=Common}\p{Script=Inherited}]
        )
    )
    (??{
        my $capture = $+{CAPTURE};
   #####printf "DEBUG: Got peekahead character %s, U+%04x\n", $capture, ord $capture;
        my $scriptname = charscript(ord $capture);
   #####print "DEBUG: Scriptname is $scriptname\n";
        my $run = q([\p{Script=Common}\p{Script=Inherited}\p{Script=)
                . $scriptname
                . q(}]*);
   #####print "DEBUG: string to re-interpolate as regex is q{$run}\n";
        $run;
    })
}x;


my $data = "foo1 and Πππ 語語語 done";

$| = 1;

while ($data =~ /($rx)/g) {
   print "Got string: '$1'\n";
}

是的,应该有更好的方法。我认为目前还没有。

所以现在,享受吧。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

用于匹配不同 Unicode 脚本之间边界的正则表达式 的相关文章

  • 为缺少字体的 Web 浏览器降低 Unicode 字符的质量

    我在 html 文档中使用 Unicode 检查标记 U 2713 我发现它在大多数浏览器中都可以正常显示 但偶尔我会遇到有人的电脑上缺少字体 如果字体丢失 是否有 HTML JS 技巧来指定替代显示字符 或图像 没有直接的方法可以判断任何
  • java regex 屏蔽列表中的所有元素,最后 4 个字符可见

    我有一个字母数字字符串列表 如下所示 nG5wnyPVNxS6PbbDNNbRsK5zanG94Et6Q4y74 GgQoDWqP7KtxXeePyyebu5EnNp8XxPC1odeNv GgQoDWqP7KtxXeePyyebu5EnN
  • 将字符串分解为标记,保持引用的子字符串完整

    我不知道我在哪里看到它 但是谁能告诉我如何使用 php 和 regex 来完成这个任务 this is a string that has quoted text inside 我希望能够像这样爆炸它 0 this 1 is 2 a 3 s
  • 正则表达式 - 匹配不包含字符串的模式

    我对正则表达式很陌生 并且一直在寻找方法来做到这一点 但没有成功 给定一个字符串 我想删除以 abc 开头 以 abc 结尾且中间不包含 abc 的任何模式 如果我做 abc abc abc 它将匹配以 b 开头 以 abc 结尾并且中间包
  • Angular 2:使用正则表达式进行数字验证

    我正在尝试验证 IE 11 中的数字字段
  • 多行 C# 正则表达式在空行后匹配

    我正在寻找一个多行正则表达式 它将匹配空行后出现的情况 例如 给定下面的示例电子邮件 我想匹配 发件人 Alex From s 可以匹配任何 From 行 但我希望它仅限于正文中的行 第一个空白行之后的任何行 Received from a
  • 需要 RegEx 返回第一段或前 n 个单词

    我正在寻找一个正则表达式来返回段落中的前 n 个单词 或者如果该段落包含少于 n 个单词 则返回完整的段落 例如 假设我最多需要前 7 个单词 p one two p
  • 使用 sed 删除非字母数字字符

    我正在尝试验证一些输入以删除一组字符 只允许使用字母数字字符加 句点 下划线 连字符 我测试了正则表达式 w here http gskinner com RegExr http gskinner com RegExr 它与我想要删除的内容
  • 正则表达式允许零,只要它不是第一个数字[重复]

    这个问题在这里已经有答案了 昨天我在这里发布了一个问题正则表达式允许 null 或 1 到 9 数字 https stackoverflow com questions 40354842 regular expression allow n
  • php 或 zend 中国际电话号码验证的正则表达式是什么?

    我有一个 zend 表单 其中有一个电话号码字段 并且必须检查验证器 我决定为此使用正则表达式 我搜索了谷歌 但我得到的结果不起作用 谁能给我提供正则表达式 这是我的代码 phone new Zend Form Element Text p
  • raku 可以避免这个 Malformed UTF-8 错误吗?

    当我运行这个 raku 脚本时 my proc run tree du out proc out slurp close say 我在 MacOS 上遇到此错误 Malformed UTF 8 near bytes ef b9 5c 而不是
  • bash 支持字边界正则表达式吗?

    我试图在再次添加该单词之前匹配列表中是否存在该单词 以避免重复 我正在使用 bash 4 2 24 并尝试以下操作 foo bmyword b also foo
  • 匹配括号内任何字符的正则表达式

    尝试创建一个与括号内的任何字符匹配的正则表达式 我的正则表达式模式是这样的 preg match listanswer answer 括号内的所有字符串都是匹配模式 但问题是 当我尝试匹配例如 this word sample data 它
  • Python re无限执行

    我正在尝试执行这段代码 import re pattern r w w s re compiled re compile pattern results re compiled search COPRO HORIZON 2000 HOR p
  • PHP URL 验证

    我知道有无数的线程问这个问题 但我一直无法找到一个可以帮助我解决这个问题的线程 我基本上试图解析大约 10 000 000 个 URL 的列表 确保它们根据以下标准有效 然后获取根域 URL 此列表包含您能想象到的几乎所有内容 包括类似的内
  • Slim 3 - 斜杠作为路由参数的一部分

    我需要使用可以包含斜杠 的参数来编写 URL 例如 经典的 hello username 路线 默认情况下 hello Fabien将匹配此路线 但不匹配 hello Fabien Kris 我想问你如何在 Slim 3 框架中做到这一点
  • 验证假名输入

    我正在开发一个允许用户输入日语字符的应用程序 我试图想出一种方法来确定用户的输入是否是日语假名 平假名 片假名或汉字 应用程序中的某些字段不适合输入拉丁文文本 我需要一种方法将某些字段限制为仅限汉字或仅限片假名等 该项目使用UTF 8编码
  • git 匹配多个单词的标签

    我们可以得到最后一个 git 标签 它以一个单词 例如 TEST 开头 如下所示 git describe tag dirty match TEST 我想知道如何获得最后一个以 word1 开头的标签orword2 例如测试OR跑步 我尝试
  • ruby 正则表达式匹配模式的多次出现

    我正在寻找构建一个 ruby 正则表达式来匹配模式的多次出现并将它们返回到数组中 模式很简单 即 两个左括号 一个或多个字符 后跟两个右括号 这就是我所做的 str Some random text lead first name and
  • 如何将 Unicode 字符转换为简单形式? [复制]

    这个问题在这里已经有答案了 有没有一个Go库可以Sj str m作为输入和返回Sjostrom作为输出 您可以使用golang org x text unicode norm来处理这个问题 package main import fmt i

随机推荐

  • 如何使用SQL Order By语句对结果进行不区分大小写的排序?

    我有一个 SQLite 数据库 我试图按字母顺序排序 问题是 SQLite 在排序过程中似乎没有考虑 A a 因此我得到这样的结果 A 乙 C 时间 A 乙 C G 我想得到 A A 乙 乙 C C G 时间 有哪些我不知道的特殊 SQL
  • 如何防止

    在超过页面宽度时被剪裁?

    我正在使用 jQuery Mobile 但我的一个页面出现了问题 我有一个 p 嵌入到列表中 如下所示 p div div h1 Page 1 h1 div div ul li List Heading li li p A very lon
  • 在 Firestore 规则中声明函数

    这是我现在面临的 Firestore 安全规则问题 首先 这是我的 firestore 数据库中的数据结构示例 userProfiles userId userData companies companyId companyData 看起来
  • 如何从 Python 包内部读取(静态)文件?

    你能告诉我如何读取 Python 包中的文件吗 我的情况 我加载的包有许多我想从程序中加载的模板 用作字符串的文本文件 但如何指定此类文件的路径呢 想象一下我想从以下位置读取文件 package templates temp file 某种
  • 以编程方式升级应用程序权限 OS X

    我做了一些挖掘 我看到的主要想法是使用 setuid getuid 和使用授权服务 由于某种原因 它在编译时给我一个符号错误 但现在似乎已被弃用 我的应用程序需要能够在某个时刻请求根访问 用于访问原始磁盘驱动器 最好使用 OS X 身份验证
  • java.lang.IllegalArgumentException:已添加:Lorg/hamcrest/BaseDescription;转换为 Dalvik 格式失败,错误 1

    首先 至少有 2 个帖子有同样的问题 但这些解决方案不再起作用 至少在我的安装中不起作用 我将 m2e 与 Eclipse 和 Android 结合使用 并尝试通过选择 run as gt Android application 将应用程序
  • 按值对对象属性进行排序

    如果我有一个 JavaScript 对象 例如 var list you 100 me 75 foo 116 bar 15 有没有办法根据值对属性进行排序 所以我最终得到 list bar 15 me 75 you 100 foo 116
  • Akka (2.3.0) 无法加载 Slf4jEventHandler 类并出现 java.lang.ClassNotFoundException

    我从 Akka 2 2 3 迁移到 2 3 0 RC4 并在应用程序启动时收到此错误消息 error while starting up loggers akka ConfigurationException Logger specifie
  • 使用node.js提示用户输入? [复制]

    这个问题在这里已经有答案了 我正在开发一个使用 node js 运行的 JS 项目 但我不知道如何让提示正确地用于用户输入 我从 npm 安装了它 按照步骤操作 我可以让程序提示用户输入 但无法将结果存储在变量中 我想要的是提示用户每回合的
  • 如何从自定义的QMessageBox中捕获按钮点击?

    如何修改下面自定义 QMessageBox 的代码才能知道用户是否单击 是 或 否 from PySide import QtGui QtCore Create a somewhat regular QMessageBox msgBox Q
  • 没有为带有 ARC 的 MKMapView 释放内存

    我有一个习惯UIView called ActivityDetailView我实例化然后添加到父视图控制器内的滚动视图 当分配此自定义视图时 每次额外的内存都会占用大约 1mb 并且 Instruments 显示内存永远不会被释放 即使视图
  • 欧拉到矩阵以及矩阵到欧拉的转换

    我正在尝试使用 NET C 将欧拉角描述的 3D 旋转转换为矩阵 然后再转换回来 我的约定是 左手系统 x 向右 y 向上 z 向前 旋转顺序 绕 y 航向 绕 x 俯仰 绕 z 倾斜 使用左手定则旋转为正 拇指指向 无穷大 我的试用是 欧
  • Magento:覆盖客户帐户控制器

    您好 我正在尝试覆盖 Mage Customer AccountController 以便我可以扩展 createPostAction 方法 对于我的一生 我似乎无法做到这一点 它要么抛出一个 404 页面 这表明它不是文件的正确路径 要么
  • Java - 需要一个记录堆栈跟踪的日志包

    是否有一个记录器可以轻松记录我的堆栈跟踪 我得到的ex printStackTrace 我搜索了 log4j 文档但什么也没找到 关于记录堆栈跟踪 我可以自己做这个 StringWriter sw new StringWriter ex p
  • 如何防止exoplayer在向后搜索时重新加载?

    我正在使用 exoplayer 播放 mp3 曲目 都好 如果轨道完全缓冲 那么在向前查找的情况下 它不会按预期重新加载 但是 如果向后查找 它会重新加载 我该如何防止这种情况 是exo的bug吗 这并不是一个真正的解决方案 但您可以使用一
  • 如何获得第二个System.Thread.ThreadPool?

    如果我以嵌套方式使用 ThreadPool 我的应用程序将挂起 ThreadPool QueueUserWorkItem state gt ThreadPool QueueUserWorkItem Action 如何获得第二个独立的Thre
  • Eq 和 Ord 实例不一致?

    我有一个大型 Haskell 程序 它运行速度慢得令人沮丧 分析和测试表明 很大一部分时间都花在比较特定大型数据类型的相等性和顺序上 这非常重要 相等是一个有用的操作 这是状态空间搜索 图搜索比树搜索更可取 但我只需要此类的 Ord 实例即
  • 元素的类名中包含(方)括号的原因是什么?

    我对这个说法感到非常惊讶class col xs 12 col sm offset 1 col sm 5 在 bootstrap 3 模板中 我不确定两者之间有什么区别 class col xs 12 col sm offset 1 col
  • sails-mysql 架构数据类型

    任何人使用节点的 sails 框架使用 mysql 作为数据库 https github com balderdashy sails mysql 我陷入模型中 无法创建数据库结构 我需要用来创建架构的数据类型不起作用 我到处搜索了一些文档
  • 用于匹配不同 Unicode 脚本之间边界的正则表达式

    正则表达式引擎有一个 零宽度 匹配的概念 其中一些对于查找单词的边缘很有用 b 存在于大多数引擎中 以匹配单词和非单词字符之间的任何边界 lt and gt 存在于 Vim 中分别仅匹配单词开头和结尾的边界 一些正则表达式引擎中的一个较新的