Confluence 6 白名单表达式类型
表达式类型
当添加一个 URL 到白名单列表中的时候,你可以选择采取下面的表达式进行添加。
域名名称(Domain name)
允许 URL 为一个指定的域名。
http://www.example.com
精确匹配(Exact match)
允许一个特定的 URL。
http://www.example.com/thispage
通配符表达式(Wildcard Expression)
允许所有匹配的 URLs。通配符 * 被用来替代一个或者多个字符。
http://*example.com
正则表达式(Regular Expression)
允许所有满足正则表达式的 URL。
http(s)?://www\.example\.com
https://www.cwiki.us/display/CONF6ZH/Configuring+the+Whitelist
《正则表达式经典实例(第2版)》——1.3 正则表达式工具
本节书摘来自异步社区《正则表达式经典实例(第2版)》一书中的第1章,第1.3节,作者: 【美】Jan Goyvaerts , Steven Levithan著,更多章节内容可以访问云栖社区“异步社区”公众号查看
1.3 正则表达式工具
除非已经拥有了相当长的使用正则表达式编程的经验,否则建议你先在一个工具中试验一下正则表达式,而不是直接在源代码中使用它们。本章和第2章中提供的正则表达式示例都是原始正则表达式,其中并不包含编程语言(即使是Unlx shell)所必需的额外的转义符号。因此可以直接把这些正则表达式输入到一个应用程序的查找框中。
第3章讲解如何把正则表达式整合到源代码中。把一个字面的(literal)正则表达式作为一个字符串引用,会让它更加难懂,因为字符串的转义规则会与正则表达式的转义规则混杂在一起。我们在实例3.1才会开始讲解这些内容。一旦理解了正则表达式的基本知识,你就能够从无数的反斜杠的背后看到“森林”。
本节要介绍的工具同样会提供调试和语法检查的功能,以及在绝大多数编程环境中并不会获得的其他反馈信息。因此,在开发应用程序时研究正则表达式的时候,你可能会发现在把一个复杂的正则表达式插入到程序中之前,首先使用这类工具试验一下可能会非常有用。1.3.1 RegexBuddy在本书写作之时,RegexBuddy(如图1-1所示)是用来创建、测试和实现正则表达式功能最为丰富的工具。它拥有独特的能力,可以仿真本书中讲到的所有正则表达式的流派,甚至可以在不同的流派之间进行转换。
RegexBuddy是由本书作者之一Jan Goyvaerts设计和开发的。设计和开发RegexBuddy使Jan成为了正则表达式的专家;由于使用了RegexBuddy,本书的另一位作者Steven迷恋上了正则表达式,最终向O’Reilly出版社建议出版这本书。
如果觉得屏幕截图(如图1-1所示)看起来比较繁杂,那是因为我们特意并排列出了大多数的面板,用来展示RegexBuddy的强大功能。实际上默认的视图会把所有的面板都很简洁地压缩成一行标签。另外,你还可以选择把一些面板拖动到另外一台显示器上。
要想尝试本书中给出的某个正则表达式,只需要把它键入RegexBuddy窗口上端的编辑框中。RegexBuddy会自动对正则表达式应用语法着色,从而使错误和括号不匹配的情形更容易看清楚。在键入正则表达式的同时,Create面板会自动构造一个用英语描述的详细分析。在该正则表达式的树中双击任意的描述,可以编辑正则表达式的对应部分。你还可以手动向正则表达式中添加新的部分,或者通过单击Insert Token按钮从菜单中选择想要的操作。例如,如果不记得肯定型顺序环视(positive lookahead)的复杂语法,可以依靠RegexBuddy来帮助添加正确的字符。
在Test面板上可以键入或者粘贴一些示例文本。当Highlight按钮激活的时候,RegexBuddy会自动高亮显示与正则表达式匹配的文本。
最经常会用到的一些按钮如下。单击上述任意一个按钮,并选择Update Automatically(自动更新),就可以让RegexBuddy在编辑正则表达式或者目标文本的时候,同步显示动态结果。
要想看到正则表达式到底会(或者不会)如何执行,在Test面板上单击一个高亮显示的匹配或者是正则表达式没有能够产生匹配的地方,然后单击Debug按钮。RegexBuddy会转到Debug面板上,逐步展示整个匹配的过程。单击调试器输出的任意地方,就可以查看哪些正则表达式记号匹配了你所单击的文本。单击正则表达式则可以在调试器中高亮显示正则表达式的该部分。
在Use面板上,选择你最喜欢的编程语言。然后,选择一个功能就可以立即生成实现该正则表达式的源代码。RegexBuddy的源代码模板可以使用内置的模板编辑器进行完整编辑。你还可以添加新的功能甚至是新的语言,或者是修改内置的模板。
如果想在一个更大的数据集上测试正则表达式,转到GREP面板上就可以在任意数量的文件和文件夹上进行查找(以及替换)。
当你在维护的源代码中发现一个正则表达式的时候,可以把它复制到剪贴板上,包括其中用于分隔的引号和斜杠。在RegexBuddy中,单击顶端的Paste按钮,并选择你的编程语言字符串风格。该正则表达式就会以原始正则表达式的形式出现在RegexBuddy中,而字符串字面量(string literal)必需的额外引号和转义符号都被去掉了。使用顶部的Copy按钮就可以创建一个按照你所要求的语法的字符串,然后可以把它重新粘贴回源代码中。
经验增长以后,用户就可以在Library面板上构建起一个便于使用的正则表达式库。在保存正则表达式的时候,别忘了添加对应的详细的描述与测试对象。即使是对专家来说,正则表达式也可能会是难以捉摸的。
如果确实无法搞明白一个正则表达式是怎么回事,可以单击Forum面板,然后单击Login按钮。如果已经购买了RegexBuddy,就会出现登录屏幕。单击OK,就会立即连接到RegexBuddy用户论坛中。Steven和Jan经常会出现在这个论坛回答用户的问题。1.3.2 RegexPalRegexPal(如图1-2所示)是由本书的作者之一Steven Levithan所创建的在线正则表达式测试工具。你所需要的仅仅是一个版本较新的网页浏览器。RegexPal全部是由JavaScript编写的。因此,它只支持JavaScript正则流派,这与你用来访问它的网页浏览器中所实现的正则表达式一样。
现在,你可以在中间的大输入框中键入或者粘贴一段样本文本。RegexPal会自动高亮与正则表达式匹配的文本。
在这个工具中并不需要单击任何按钮,因此RegexPal是最为方便的在线正则表达式测试工具之一。
1.3.3 RegexMagicRegexMagic(如图1-3所示)是另一款由Jan Goyvaerts设计和开发的工具软件。RegexBuddy的目标是可以更为容易地处理正则表达式语法,而RegexMagic则主要设计给那些不愿意接触正则表达式语法,更不肯读500页正则表达式图书的人。在RegexMagic中,可以基于样本文本和RegexMagic的高级别模式描述想要匹配的文本。屏幕截图中演示了只需选择“Email address”(电子邮件地址)模式,即可得到一个匹配电子邮件地址的正则表达式。你也可以自定义模式以限制允许的用户名和主机域名,并且可以选择是否允许或必需mailto:前缀。
既然选择了读这本书,那你已经身处精通正则表达式的道路上。RegexMagic不应成为你使用正则式的主要工具,但在一些情况下它仍然十分便利。在实例6.7中我们讲解了该如何创建一个正则表达式来匹配一个范围内的数值字符串。尽管用正则表达式来判断一个数值字符串是否在某个范围内并不是最好的方法,但有时只能使用正则表达式来解决问题。内置正则引擎的应用程序远比内置脚本语言的多得多。虽然实例6.7中描述的技术没有什么难度,但手动完成这项工作还是十分枯燥乏味。
试想一下,如果要匹配的十进制数字位于2 147 483 648(231)到4 294 967 295(232–1)的范围内,而不是实例6.7中那些简单的示例。在RegexMagic中,只需选择“Integer”(整数)模式,选择“decimal”(十进制)选项,并将范围限制在2147483648..4294967295。在“strict”(严格)模式下,RegexMagic会立即生成如下“望而生畏的正则式”:
\b(?:429496729[0-5]|42949672[0-8][0-9]|4294967[01][0-9]{2}|429496[0-6]↵
[0-9]{3}|42949[0-5][0-9]{4}|4294[0-8][0-9]{5}|429[0-3][0-9]{6}|42[0-8]↵
[0-9]{7}|4[01][0-9]{8}|3[0-9]{9}|2[2-9][0-9]{8}|21[5-9][0-9]{7}|214[89]↵
[0-9]{6}|2147[5-9][0-9]{5}|214749[0-9]{4}|214748[4-9][0-9]{3}|2147483↵
[7-9][0-9]{2}|21474836[5-9][0-9]|214748364[89])\b
正则选项:无
正则流派:.NET、Java、JavaScript、PCRE、Perl、Python、Ruby
1.3.4 更多正则表达式在线测试工具创建一个简单的正则表达式在线测试工具并不困难。如果你拥有一些基本的Web开发技能,那么只需要第3章中的信息就足以构建自己的正则表达式工具了。成百上千的人已经这样做过,其中有些人还添加了一些额外的功能,值得加以介绍。
1.RegexPlanetRegexPlanet(http://www.regexplanet.com/)是由Andrew Marcuse开发的网站。它出名的原因是它允许用户在很多种正则库中测试正则式,比我们知道的任何一个网站都要多。在首页上可以找到这些语言的测试工具链接,包括Java、JavaScript、.NET、Perl、PHP、Python和Ruby。它们都使用相同的基本界面。只有选项列表依据各编程语言而定。图1-4演示的是.NET版本。
在“regular expression”文本框键入或粘贴正则表达式。如果想要测试“查找和替换”,在“replacement”文本框中粘贴替代文本。你可以在任意数量的不同目标字符串上测试正则表达式,将目标字符串粘贴到各“input”文本框中即可。如果需要5个以上文本框,单击“more inputs”。虽然“regex”和“input”文本框只会显示一行,但是可以键入或粘贴多行文本。滚动箭头显示在文本框右侧。
输入完后,点击“test”按钮将所有字符串发送到regexplanet.com服务器。结果页面(如图1-4所示)会在顶部列出所有测试结果。前两行显示你的输入,余下各行显示不同函数的执行结果。站点支持的各编程语言的结果格式各不相同。
2.regex.larsolavtorvik.comLars Olav Torvik在http://regex.larsolavtorvik.com(如图1-5所示)建立了一个非常优秀小巧的在线正则表达式测试工具。首先,用户可以单击在页面上端的流派名称来选择正在使用的正则表达式流派。Lars提供了PHP PCRE、PHP POSIX和JavaScript。PHP PCRE,也就是本书中介绍的PCRE正则流派,是由PHP的preg函数使用的。POSIX是由PHP的ereg函数使用的是一种较陈旧且功能有限的正则表达式流派,在本书中并没有讨论这种流派。如果用户选择JavaScript,那么使用的就是你的浏览器中所实现的JavaScript正则表达式。
在Pattern域中输入正则表达式,并在Subject域中输入目标文本。稍等片刻,在Matches域中就会显示高亮之后的正则表达式匹配的目标文本。Code域中显示把正则表达式应用到目标文本之上的一行源代码。把这段代码复制并粘贴到代码编辑器中可以节省大量时间,因为不必再费力气手动把正则表达式转换成一个文本字符串。该代码返回的任何字符串或者数组都会显示在Result域中。因为Lars使用了Ajax技术来构建他的网站,所以所有的流派都只需片刻就可以更新其结果。如果要使用该工具,电脑就必须保持联网状态,因为PHP是在服务器端进行处理的,而不是在浏览器中。第二列给出了正则表达式命令和选项列表。这些依据你所选择的正则表达式流派而定。正则表达式命令通常包括匹配、替换和拆分操作。正则表达式选项包含常见的选项,如不区分大小写,以及与实现有关的一些选项。这些命令和选项会在第3章中讲解。
3.Nregexhttp://www.nregex.com(如图1-6所示)是由David Seruyange开发的一个很简明的在线正则表达式测试工具。它支持.NET 2.0的正则流派,.NET 3.0、3.5和4.0也同样适用。
这个网页的布局看起来有些让人费解。在Regular Expression标签下面的域中输入正则表达式,并且使用其下的复选框来设定正则表达式选项。然后在底部的大输入框中键入目标文本,替换掉默认的If I just had $5.00 then "she" wouldn't be so @#$! mad.。如果你的目标是一个网页的话,那么可以把它的URL键入Load Target From URL域中,然后单击该输入域之下的Load按钮。如果目标是在硬盘上的一个文件,那么单击Browse1FF(浏览)按钮,找到想要使用的文件,然后单击该输入域之下的Load按钮。
目标文本会重复出现在网页中心的Matches & Replacements域中,其中正则表达式的匹配会高亮显示。如果在Replacement String域中敲入一些内容,那么这里就会显示查找和替换后的结果。如果正则表达式是非法的,那么就会出现…(省略号)。正则表达式的匹配是通过在服务器上运行的 .NET代码来完成的,所以也需要保持联网状态才能使用该网站。如果发现自动更新的速度比较慢的话,那可能是因为目标文本非常长,选中正则表达式输入域之上的Manually Evaluate Regex复选框,就会出现Evaluate按钮。单击该按钮就可以更新Matches & Replacements的显示。
4.RubularMichael Lovitt在http://www.rubular.com(如图1-7所示)建立了一个最小功能集的在线正则表达式测试工具。写作本书时,它允许用户在Ruby 1.8.7和Ruby 1.9.2间选择。这让你可以同时测试本书使用的Ruby 1.8和Ruby 1.9的正则表达式流派。
在Your regular expression下面两个正斜杠之间的文本框中输入正则表达式。你可以通过在第二个斜杠之后的小输入框中键入一个i来开启不区分大小写选项。相类似,如果需要的话还可以在同一个输入框中键入一个m来开启“点号匹配换行符”的选项。而键入im则会同时开启这两个选项。如果你是刚刚接触Ruby的话,可能会觉得这些约定看起来对用户有点儿不够友好,但是它们与用来在Ruby代码中指定正则表达式时所使用的/regex/im语法是一致的。在Your test string文本框中输入或者粘贴目标文本。在右边会出现一个新的Match results文本框,用来显示所有正则表达式匹配高亮显示之后的目标文本。
5.myregexp.comSergey Evdokimov为Java开发人员创建了多个正则表达式测试工具。在http://www.myregexp.com网站主页(如图1-8所示)提供了其中一个在线正则表达式测试工具。它是一个在浏览器中运行的Java applet(小程序)。在你的计算机上需要安装Java 4(或更新版本)运行时。这个小程序使用java.util.regex包来运行正则表达式,这个包是在Java 4中新引入的。在本书中,“Java”正则流派指的就是这个包。
在Regular Expression输入框中输入正则表达式。使用Flags菜单来设置你想用的正则选项。其中三个选项也可以直接使用复选框。如果想要测试存在于Java代码字符串变量中的正则表达式的话,可以把整个字符串都复制到剪贴板上。在myregexp.com测试工具中,单击Edit菜单,然后选择Paste Regex from Java String(粘贴来自Java字符串的正则式)。完成了正则表达式的编辑之后,在同一个菜单中选择Copy Regex for Java Source(复制Java代码所使用的正则式)。Edit菜单对于JavaScript和XML也有类似的命令。
在正则表达式下面,有4个标签,可以用来运行4种不同的测试。1.3.5 更多桌面正则表达式测试工具1.ExpressoExpresso(不要把它和富含咖啡因的浓咖啡espresso混为一谈)是用来创建和测试正则表达式的一个 .NET应用程序。可以从http://www.ultrapico.com/Expresso.htm下载它。你的计算机上必须安装有.NET Framework 2.0或者更新版本。
从网站下载的是一个60天免费试用版。在试用期过后,必须注册该软件,否则Expresso就(大体上)无法使用了。注册码通过电子邮件发送。
Expresso会显示一个类似图1-9所示的屏幕。用来输入正则表达式的Regular Expression文本框是始终保留的。它并不会进行任何语法着色。Regex Analyzer框则会为正则表达式自动构造一个简要的英语语言分析。它同样是始终保留的。
在Design Mode(设计模式)下,可以在屏幕的底部设置诸如“Ignore Case”(忽略大小写)这样的匹配选项。屏幕空间的大部分被一排标签页所占据,可以在此选择想要插入的正则表达式记号。如果你拥有两个显示器,或者一个大的显示器,可以单击Undock按钮来使这行标签页都悬浮起来。接着仍然可以在另一模式(Test Mode)下构建正则表达式。
在Test Mode(测试模式)下,可以在屏幕左下角输入或者粘贴示例代码。然后,单击Run Match按钮,就可以在Search Results文本框中得到所有匹配的列表。这里并不会对示例文本应用任何的高亮显示。在结果中单击一个匹配就可以选中在示例文本中对应的匹配。
Expression Library会给出样例正则表达式的列表,以及最近使用的正则表达式列表。每次按下Run Match的时候,当前的正则表达式都会添加到这个列表中,可以通过在主菜单工具条上的Library菜单来编辑这个表达式库。2.The Regulator可以从http://sourceforge.net/projects/regulator下载的The Regulator对佩戴水中呼吸器潜水或是使用煤气罐来说并不安全2FF,它是另外一个用来创建和测试正则表达式的 .NET应用。它的最新版本要求 .NET 2.0或者更新版本。你还可以下载到用于 .NET 1.x的较早版本。The Regulator是开源软件,不需要付钱或者注册。
The Regulator会在一个屏幕(如图1-10所示)中完成所有的工作。New Document标签页是用来输入正则表达式的地方。语法着色会自动生效,但是在正则表达式中的语法错误却不会突出显示。单击鼠标右键可以从一个菜单中选择想要添加的正则表达式记号,也可以通过主工具条之上的按钮来设置正则表达式选项。这些图标看起来会有些费解,可以让鼠标稍作停留,等待提示出现,就能看到每个按钮可以设置什么选项了。
在正则表达式区域下面的右边,单击Input按钮就会显示可以用来粘贴样本文本的区域。如果想要进行查找和替换操作的话,可以单击Replace with按钮来键入替代文本。在正则表达式下面偏左的地方,你会看到该正则表达式操作的结果。它的结果不会进行自动更新;必须单击工具条中的Match、Replace或Split按钮才能更新结果。而且,它也不会对输入应用高亮显示。单击结果中的一个匹配,可以看到要它在目标文本中的位置。Regex Analyzer面板展示的是对正则表达式进行的简单的语言分析,它既不是自动的,也不能逐步互动。要想更新这个分析结果,需要在View菜单中选择Regex Analyzer,即使它已经显示也需要这样做。如果仅仅单击分析结果,只有文本指针会移动。
3.SDL Regex FuzzerSDL Regex Fuzzer这个含混的(fuzzy)名字没有明显表示出它的用途。微软公司宣称它是“帮助测试正则表达式中潜在的拒绝服务漏洞的工具”。可以从http://www.microsoft. com/ n-us download details.aspx?id=20095免费下载。需要安装.NET 3.5来运行它。
SDL Regex Fuzzer真正所做的是,检查是否存在一个可以使正则表达式需要指数级时间来执行的目标字符串。本书中我们称这为“灾难性回溯”。我们会在实例2.15中详细讲解这一点,并提供了一种可用的解决方案。简单说,引起灾难性回溯的正则式会让应用程序停止响应或是崩溃。如果程序是服务器应用,这可能会导致拒绝服务攻击。
图1-11显示了SDL Regex Fuzzer的一个测试结果。在Step 1中我们粘贴了实例2.15中的正则表达式。因为这个表达式无法匹配非ASCII码字符,所以无需在Step 2中选择All ASCII characters (所有ASCII码字符) 这一选项。否则,则应选择。在Step 3中我们保留默认的100次循环。单击Step 4的Start按钮,大约5秒后,SDL Regex Fuzzer显示了一个样例字符串,这个字符串会使正则式在.NET 3.5中执行失败。
遗憾的是,这个工具的实用性非常有限,因为它只支持.NET正则语法的一个小子集。而当我们试图测试实例2.15中的原始解决方法时,遇到了图1-12所示的错误消息,即便该正则式明显无法通过测试。正确理解实例2.15中所讨论的概念,是确保应用程序不被复杂的正则表达式拖垮的唯一途径。1.3.6 grepgrep这个名字是从g/re/p命令推衍而来的,这个命令在Unix文本编辑器ed中用于正则表达式查找,而ed则是最早支持正则表达式的应用之一。该命令非常流行,结果所有的UNIX系统中现在都包含一个专门的grep工具以便在文件中进行正则表达式查找。如果你在使用UNIX、Linux或者OS X,那么在终端窗口中键入man grep命令就可以学习这个命令的全部知识。
下面的3个工具是用来实现与grep相同的功能的Windows应用程序,而且它们还添加了额外的功能。
1.PowerGREP由本书作者之一Jan Goyvaerts所开发的PowerGREP,可能是在Microsoft Windows平台上可用到的功能最为丰富的grep工具(如图1-13所示)。PowerGREP使用一种定制的正则表达式流派,它兼具本书中介绍的各流派中最好的特性。这种流派在RegexBuddy中称为“JGsoft”。
要执行一次快速的正则表达式查找,只需在Action菜单中选择Clear,并在Action面板上的Search框中输入正则表达式。在File Selector面板上单击一个文件夹,然后在File Selector菜单中选择Include File or Folder或Include Folder and Subfolders。接着在Action菜单中选择Execute就可以进行查找。
要执行一次查找和替换操作,在清除了上述操作之后,在Action面板左上角处的action type下拉列表中选择search-and-replace。Search框下即会显示一个Replace框,在这里输入替代文本。其余所有的步骤都与查找功能完全相同。
PowerGREP具有独特的能力,可以在同一时刻使用最多5个正则表达式列表,在每个列表中可以包含任意数目的正则表达式。虽然上面两段已经给出了足够的信息,让你可以像使用其他任何grep工具一样执行一些简单的搜索,但是要发挥PowerGREP的全部潜力则需要多花点儿时间通读一下该工具的详细文档。
PowerGREP可以在Windows 2000/XP/Vista/7/8上运行。可以从http://www.powergrep.com/PowerGREPCookbook.exe下载免费评估版本。除了保存结果和库之外,试用版包含了可以实际使用15天的全部功能。尽管试用版不能保存在Results面板上显示的结果,但是它也和完整版本一样,会执行查找和替换操作修改所有文件。
2.Windows GrepWindows Grep(http://www.wingrep.com)是在Windows平台上最古老的grep工具之一。它的年代可以从它的用户界面中看出一点儿端倪(如图1-14所示),但它的确可以实现他所标榜的功能。它支持一种功能有限的正则表达式流派,这种流派被称作POSIX ERE。对于它支持的功能,它所使用的语法与本书中介绍的流派是一样的。Windows Grep是一个共享软件,这意味着你可以免费下载它,但是如果希望长时间使用,就需要付费。
要想执行搜索,在Search菜单中选择Search。接下来出现的屏幕将会根据你在Options菜单中所选择的是Beginner Mode(初学者模式)或是Expert Mode(专家模式)而有所不同。初学者会看到逐步向导,而专家则会看到标签页对话框。
设置好搜索之后,Windows Grep会立即执行它,并向你展示一个在其中找到匹配的文件列表。单击一个文件就可以在底部面板中看到其中的匹配,而双击一个文件会打开该文件。在View菜单中选择All Matches会使底部面板显示所有内容。
如果想要执行查找和替换,只需要在Search菜单中选择Replace即可。
3.RegexRenamerRegexRenamer(如图1-15所示)实际上并不是一个grep工具。它并不查找文件的内容,而是查找和替换文件的名称。可以从http://regexrenamer.sourceforge.net下载该工具。RegexRenamer要求安装Microsoft .NET Framework2.0或者更新版本。
在Match框中键入正则表达式,并在Replace框中键入替代文本。单击/i可以打开不区分大小写选项,单击/g则会替换每个文件名中的所有匹配,而不只是替换第一个匹配。选择/x会打开宽松排列(free-spacing)的语法选项,这并不是很有用,因为只有一行空间可以输入正则表达式。
使用左边的树可以选择包含你想要重命名的文件的文件夹。在右上角,可以设置一个文件名通配符掩码或者正则表达式过滤器。这可以限制“查找和替换”正则表达式所应用的文件列表。与其试图只使用一个正则表达式来完成所有工作,更方便的做法是用一个正则表达式进行过滤,用另一个正则表达式进行替换。
1.3.7 常见的文本编辑器大多数现代的文本编辑器都至少支持基本的正则表达式。在查找或者查找和替换面板上,你通常会发现一个复选框可以打开正则表达式模式。有些编辑器,如EditPad Pro,也会使用正则表达式来完成各种文本处理的功能,如语法高亮显示或是类和函数列表等。每个编辑器所带的文档会详细讲解所有这些功能。下面列出了一些支持正则表达式的常用文本编辑器。
BBEdit(PCRE)
Boxer Text Editor(PCRE)
Dreamweaver(JavaScript)
EditPad Pro(组合了本书中介绍的流派中最好部分的一种定制流派;在RegexBuddy中称作是“JGsoft”)
Multi-Edit(PCRE,需要选择“Perl”选项)
Nisus Writer Pro(Ruby 1.9 [Oniguruma])
Notepad++(PCRE)
NoteTab(PCRE)
UltraEdit(PCRE)
TextMate(Ruby 1.9 [Oniguruma])
正则 (入门篇)
如果你对正则感兴趣,读完这篇文章,一定会有收获~_^
简单来说
正则一般代指正则表达式
正则表达式是从"复杂数据"中抽取"有用数据"的公式
写好正则表达式的两个要点:
1.正确匹配字符数量(相关符号:*,+,?,{})
2.正确匹配字符种类(相关符号:除上面符号以外的其它符号^_~)
相关符号
.代表"万能匹配";//可以匹配除了"\n"(换行符)之外的任何单个字符
?代表"不要贪婪";//用在*,+,?后面,表示匹配的越少越好
?也代表"非〇即一";
^代表"除了你";//在中括号内,如[^_]表示单个非下划线字符
^也代表"匹配首位";
$代表"匹配末位";
*代表"〇至无穷"; //大于等于0的整数
+代表"一至无穷";//大于等于1的整数
|代表"我们都一样";//|表示"或"
\d代表"匹配数字";//0-9
\D代表"匹配非\d"
\w代表"匹配字符";//0-9,A-Z,a-z,_
\W代表"匹配非\w"
几个括号
大括号{}用来确定数量
re.match表示正则模块里面的match函数(match函数默认从字符串首部开始匹配),\d匹配单个数字{3}代表匹配3个
image.png
中括号[]用来确定匹配字符的种类
第一种写法
re.match(r"[123]{1}根烟","1根烟")
re.match(r"[123]{1}根烟","2根烟")
re.match(r"[123]{1}根烟","3根烟")
image.png
中括号内的123可匹配单个1或2或3
第二种写法
re.match(r"[1,2,3]{1}根烟","1根烟")
re.match(r"[1,2,3]{1}根烟","2根烟")
re.match(r"[1,2,3]{1}根烟","3根烟")
image.png
小括号()用来为表达式整体匹配后,"按需提取"(经常和函数group配合使用)
如提取域名中的词组(以简书域名为例)
re.match(r".*//.*?\.+(.*?)\.+[^\.]*","http://www.bilibili.com").group(1)
image.png
什么是贪婪匹配?
贪婪的总是尝试匹配尽可能多的字符;(大多编程语言的正则默认贪婪)
在*,?,+,{m,n}后面加上?即可使贪婪变成非贪婪.
写在最后
正则表达式相当于编程的小九九,背的时候有点恶心,但用起来非常爽!
正则表达式,最早用于唯一标示复杂的神经网络,现可用于"唯一标示"某个字符串,也就是"唯一匹配"字符串
正则表达式使用了大量的特殊字符,这些特殊字符在不同的语境下还会有不同的含义,所以正则的表达式看起来有点像乱码(表象无序的乱码,底层极致的规范)
实战JS正则表达式
原文:实战JS正则表达式
-正则表达式是一种文本模式的匹配工具。
-文章导读:
--1.正则对象的属性和方法
--2.字符串对象的方法
--3.使用正则表达式:
---3.1 给字符串加上千分符
---3.2 字符串中出现次数最多的字母
---3.3 在多行中使用正则表达式
---3.4 从url中提取子域名
---3.5 分割Unicode字符
---3.6 在location对象中使用正则
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
[新建正则表达式]:
1 var regexp = /aabb/g; //g可省
2 var regexp = new Regexp("xyz","g"); //第二个参数可省
区别在于:
1.采用字面量的写法新建的正则表达式对象在代码编译时就会生成,是平常开发中常用的方式;
2.采用构造函数生成的正则对象要在代码运行时生成。
[使用正则表达式]:
正则对象的方法是指这样使用的: RegExp对象.方法(字符串)
字符串对象的方法是这样使用:字符串.方法(RegExp对象)
一、 正则对象的属性和方法
1.1 正则对象的属性:
1 ignoreCase //返回一个布尔值表示正则对象是否设置了i修饰符,是一个只读属性
2 global //表示正则对象是否设置了g修饰符,返回布尔值
3 multiline //表示是否设置了m修饰符,返回一个布尔值
4 lastIndex //返回下一次开始搜索的位置,该属性可读写,但只在设置了g修饰符时有意义
5 source //返回正则表达式的字符串形式(不包括反斜杠),只读属性
这样用:
1 i --执行忽略大小写的匹配
2 g --执行全局匹配(可以查看所有的匹配而不是只找到第一个匹配后就停止)
3 m --执行多行匹配
1.2 test方法
test方法返回布尔值,用来验证字符串是否符合某个模式。如果正则表达式带有g修饰符,则每一次test方法都从上一次匹配结束的位置开始匹配。
使用了g修饰符的正则对象,表示要记录搜索的位置,接着使用test方法,每次开始搜索的委会都是上一次匹配的后一个位置:
如果正则表达式是一个空字符串,则会匹配所有的字符串,但前提是使用new RegExp()的方式:
1.3 exec方法
exec()返回匹配的结果,匹配成功exec方法返回装有匹配结果的数组,匹配失败返回null:
如果正则表达式包含圆括号,则返回的数组会包括多个元素。首先是整个匹配成功的结果,后面是圆括号里匹配成功的结果,如果有多个圆括号,他们的匹配成功的结果都会成为数组元素:
对于调用exec方法后返回的数组具有以下两个属性:
1 input --整个原待匹配的字符串
2 index --整个模式匹配成功的开始位置
同样,给正则表达式加上g修饰符就可以多次使用exec方法,下一次搜索的位置从上一次成功匹配结束的位置开始。
如果正则对象是一个空字符串:
二、字符串对象的方法
1 match-----返回匹配的子字符串
2 search----搜索
3 replace---替换
4 split-----分割
2.1 match()方法
字符串对象的match方法与正则对象的exec方法比较类似:
但是如果正则表达式带有g修饰符,那么match方法与exec方法就有差别了:
可以看到match返回了所有成功匹配的结果,但是exec方法只返回了一个。
2.2 search方法
search方法返回匹配成功的位置在整个字符串中的索引,如果没有匹配成功任何字符则返回-1,search方法会自己忽略g修饰符。
2.3 replace方法
str.replace('搜索模式','替换的内容');
可以看到,如果正则表达式不带g修饰符,那么replace方法会替换第一个匹配成功的结果,如果加上了g修饰符,那么会替换所有匹配成功的值。
replace方法的第二个参数可以使用$符号,用来指代所要替换的内容:
1 $&-----指代匹配的字符串
2 $`-----匹配结果前面的文本
3 $'-----匹配结果后面的文本
4 $n-----指代匹配成功的第n组内容,n从1开始
5 $$-----指代美元符号$
replace方法的第二个参数也可以是函数,用于将第一个参数匹配到的值替换为函数返回值。
同时,作为replace方法的第二个参数的函数也可以由多个参数。它的第一个参数是整个匹配的内容,第二个参数是组匹配(这时有多少个组匹配就有多少个参数),此外最后还可以添加两个参数,倒数第二个参数是扑捉到的内容在整个字符串中的位置,最后一个参数是原字符串。
2.4 split() 方法
split(‘字符串的分割正则’,‘返回数组的最大成员数’);返回分割后各部分组成的数组。
可以变换正则的匹配规则来分割字符串。
上面正则的匹配规则是以0或多个a来进行分割,如果加上括号则括号匹配的部分也就是分割规则也会作为数组成员返回。
三、使用正则表达式
正则表达式不仅灵活还很强大,用它能很简洁的实现很多实用的功能,下面简单列举一些:
3.1给字符串加千分符
1 function spli(str){
2 var re = /(?=(?!\b)(\d{3})+$)/g;
3 return str.replace(re,',');
4 }
5 console.log(spli(str));
其中的(?=exp)用来匹配exp前面的位置,(?!exp)匹配后面跟的不是exp的位置,他们都是零宽断言。
如果要是不用正则表达式的话,代码会多些:
1 var str = '12345432';//->[]
2 function spli(str){
3 var iNum = str.length%3;//->0,1,2
4 var prev = '';
5 var arr = [];
6 var iNow = 0;
7 var tmp = '';
8 //千分号是从后向前三位三位加的,所以把三位余出来的从前面提取到
9 if(iNum !=0){
10 prev = str.substring(0,iNum);
11 arr.push(prev);
12 }
13 //取到多余部分后面的
14 str = str.substring(iNum);
15 for(var i=0;i<str.length;i++){
16 iNow++;
17 tmp += str[i];
18 if(iNow==3 && tmp){
19 //数组里面放的是三位的数
20 arr.push(tmp);
21 tmp = '';
22 iNow = 0;
23 }
24 }
25 return arr.join(',');
26 }
27 console.log(spli(str));
View Code
3.2字符串中出现次数最多的字符
1 var str = 'kkkkkkkaaakkkkkkaaaaasddd';
2 function most(str){
3 //排序,正则匹配子项
4 var arr = str.split('');
5 arr.sort();
6 str = arr.join('');
7 // \1匹配前面相同的,也就是说跟(\w)相同的
8 var re = /(\w)\1+/g;
9 var num = 0;
10 var value = '';
11 //这里的$0就是找到的重复的整体
12 str.replace(re,function($0,$1){
13 //alert($0);
14 if(num<$0.length){
15 num = $0.length;
16 value = $1;
17 }
18 });
19 return '出现次数最多的字符是'+value+'出现了'+num+'次';
20 }
21 console.log(most(str));
其中\1代表分组1匹配的文本。
3.3 在多行中使用正则表达式
^符号用来匹配输入/字符串的开始。如果多行(multiline)标志被设为 true,该字符也会匹配一个断行(line break)符后的开始处。
3.4 从url中提取子域名
上面的正则匹配/开始的字符串匹配到第一个.就停止了,http://长度为7,所以用了substr(7)之后就会返回子域名了。
3.5 分割Unicode字符
通常用来匹配字符的\w和\W只会匹配基本的ACSCII字符,要匹配Unicode字符的话就要另做处理了:
3.6 在location对象中使用正则
这里有个我越看越晕的例子,额:
来自小胡子==。[玩转正则之highlight高亮]
四、其他
正则表达式的收集:
[常用的正则表达式收集]
[ js常用正则表达式]
参考资料:
[RegExp MDN]
[玩转正则之highlight高亮]
这里我只是总结了正则表达式相关的方法和属性,强烈建议阅读:正则表达式30分钟入门教程 它教会你如何写正则表达式,再结合文章上面提到的方法,写着写着,正则就不是那么遥不可及了,非常实用喔。
正则表达式中的反向预搜索(续)
在前面《正则表达式中的反向预搜索》
中,在JavaScript中利用RegExp对象实现了正则表达式反向预搜索的字符串替换功能,代码为:
//程序目的,去掉图片路径中的域名
var str = '<img src="http://news.163.com/sports/yao.jpg">';
var reg1 = /(/<img)(.*(?=(http|https)/:////))((http|https)/:////[^//]*)/gim;
str.match(reg1);
alert(str.replace(RegExp.$4,'');
这个用法在字符串中只有一个URL时,是适用的,但是如果字符串中包含多个域名,例如:
var str = '<img src="http://news.163.com/sports/yao.jpg">网易首页的<a href="http://www.163.com">链接</a>';
程序运行后去掉的内容就是第二个域名即http://www.163.com。这是为什么呢?
仔细查看正则表达式会发现,在使用"(/<img)
"匹配了<img之后,使用“.*”匹配所有字符直到“http://”或者“https://”。请注意,正是“.*”导致了这个问题的出现,这里的“.*”就是说,一直查找和匹配,尽可能的多匹配,直到最后一个限定符,也就是说术语中的贪婪(greedy)匹配。很自然,就想到了使用非贪婪的匹配解决这个问题。把正在表达式改为:
//与贪婪匹配的差别就是多了一个问号“?”,贪婪".*",非贪婪".*?"
var reg1 = /(/<img)(.*?(?=(http|https)/:////))((http|https)/:////[^//]*)/gim;
解决问题的方法很简单,但是也说明平时工作存在的一个重要问题:程序测试不充分。
一个正则表达式酿成的惨案…
前几天线上一个项目监控信息突然报告异常,上到机器上后查看相关资源的使用情况,发现 CPU 利用率将近 100%。通过 Java 自带的线程 Dump 工具,我们导出了出问题的堆栈信息。
我们可以看到所有的堆栈都指向了一个名为 validateUrl 的方法,这样的报错信息在堆栈中一共超过 100 处。通过排查代码,我们知道这个方法的主要功能是校验 URL 是否合法。
很奇怪,一个正则表达式怎么会导致 CPU 利用率居高不下。为了弄清楚复现问题,我们将其中的关键代码摘抄出来,做了个简单的单元测试。
当我们运行上面这个例子的时候,通过资源监视器可以看到有一个名为 java 的进程 CPU 利用率直接飙升到了 91.4% 。
看到这里,我们基本可以推断,这个正则表达式就是导致 CPU 利用率居高不下的凶手!
于是,我们将排错的重点放在了那个正则表达式上:
^([hH][tT]{2}[pP]://|[hH][tT]{2}[pP][sS]://)(([A-Za-z0-9-~]+).)+([A-Za-z0-9-~\\/])+$
这个正则表达式看起来没什么问题,可以分为三个部分:
第一部分匹配 http 和 https 协议
第二部分匹配 www. 字符
第三部分匹配许多字符
我看着这个表达式发呆了许久,也没发现没有什么大的问题。
其实这里导致 CPU 使用率高的关键原因就是:Java 正则表达式使用的引擎实现是 NFA 自动机,这种正则表达式引擎在进行字符匹配时会发生回溯(backtracking)。而一旦发生回溯,那其消耗的时间就会变得很长,有可能是几分钟,也有可能是几个小时,时间长短取决于回溯的次数和复杂度。
看到这里,可能大家还不是很清楚什么是回溯,还有点懵。没关系,我们一点点从正则表达式的原理开始讲起。
正则表达式引擎
正则表达式是一个很方便的匹配符号,但要实现这么复杂,功能如此强大的匹配语法,就必须要有一套算法来实现,而实现这套算法的东西就叫做正则表达式引擎。简单地说,实现正则表达式引擎的有两种方式:DFA 自动机(Deterministic Final Automata 确定型有穷自动机)和 NFA 自动机(Non deterministic Finite Automaton 不确定型有穷自动机)。
对于这两种自动机,他们有各自的区别,这里并不打算深入将它们的原理。简单地说,DFA 自动机的时间复杂度是线性的,更加稳定,但是功能有限。而 NFA 的时间复杂度比较不稳定,有时候很好,有时候不怎么好,好不好取决于你写的正则表达式。但是胜在 NFA 的功能更加强大,所以包括 Java 、.NET、Perl、Python、Ruby、PHP 等语言都使用了 NFA 去实现其正则表达式。
那 NFA 自动加到底是怎么进行匹配的呢?我们以下面的字符和表达式来举例说明。
text="Today is a nice day."regex="day"
要记住一个很重要的点,即:NFA 是以正则表达式为基准去匹配的。也就是说,NFA 自动机会读取正则表达式的一个一个字符,然后拿去和目标字符串匹配,匹配成功就换正则表达式的下一个字符,否则继续和目标字符串的下一个字符比较。或许你们听不太懂,没事,接下来我们以上面的例子一步步解析。
首先,拿到正则表达式的第一个匹配符:d。于是那去和字符串的字符进行比较,字符串的第一个字符是 T,不匹配,换下一个。第二个是 o,也不匹配,再换下一个。第三个是 d,匹配了,那么就读取正则表达式的第二个字符:a。
读取到正则表达式的第二个匹配符:a。那着继续和字符串的第四个字符 a 比较,又匹配了。那么接着读取正则表达式的第三个字符:y。
读取到正则表达式的第三个匹配符:y。那着继续和字符串的第五个字符 y 比较,又匹配了。尝试读取正则表达式的下一个字符,发现没有了,那么匹配结束。
上面这个匹配过程就是 NFA 自动机的匹配过程,但实际上的匹配过程会比这个复杂非常多,但其原理是不变的。
NFA自动机的回溯
了解了 NFA 是如何进行字符串匹配的,接下来我们就可以讲讲这篇文章的重点了:回溯。为了更好地解释回溯,我们同样以下面的例子来讲解。
text="abbc"regex="ab{1,3}c"
上面的这个例子的目的比较简单,匹配以 a 开头,以 c 结尾,中间有 1-3 个 b 字符的字符串。NFA 对其解析的过程是这样子的:
首先,读取正则表达式第一个匹配符 a 和 字符串第一个字符 a 比较,匹配了。于是读取正则表达式第二个字符。
读取正则表达式第二个匹配符 b{1,3} 和字符串的第二个字符 b 比较,匹配了。但因为 b{1,3} 表示 1-3 个 b 字符串,以及 NFA 自动机的贪婪特性(也就是说要尽可能多地匹配),所以此时并不会再去读取下一个正则表达式的匹配符,而是依旧使用 b{1,3} 和字符串的第三个字符 b 比较,发现还是匹配。于是继续使用 b{1,3} 和字符串的第四个字符 c 比较,发现不匹配了。此时就会发生回溯。
发生回溯是怎么操作呢?发生回溯后,我们已经读取的字符串第四个字符 c 将被吐出去,指针回到第三个字符串的位置。之后,程序读取正则表达式的下一个操作符 c,读取当前指针的下一个字符 c 进行对比,发现匹配。于是读取下一个操作符,但这里已经结束了。
下面我们回过头来看看前面的那个校验 URL 的正则表达式:
^([hH][tT]{2}[pP]://|[hH][tT]{2}[pP][sS]://)(([A-Za-z0-9-~]+).)+([A-Za-z0-9-~\\/])+$
出现问题的 URL 是:
http://www.javastack.cn/dzfp-web/pdf/download?request=6e7JGm38jfjghVrv4ILd-kEn64HcUX4qL4a4qJ4-CHLmqVnenXC692m74H5oxkjgdsYazxcUmfcOH2fAfY1Vw__%5EDadIfJgiEf
我们把这个正则表达式分为三个部分:
第一部分:校验协议。^([hH][tT]{2}[pP]://|[hH][tT]{2}[pP][sS]://)。
第二部分:校验域名。(([A-Za-z0-9-~]+).)+。
第三部分:校验参数。([A-Za-z0-9-~\\/])+$。
我们可以发现正则表达式校验协议 http:// 这部分是没有问题的,但是在校验 www.javastack.cn 的时候,其使用了 xxxx. 这种方式去校验。那么其实匹配过程是这样的:
匹配到 www.
匹配到 javastack.
匹配到 cn/dzfp-web/pdf/download?request=6e7JGm38jf.....,你会发现因为贪婪匹配的原因,所以程序会一直读后面的字符串进行匹配,最后发现没有点号,于是就一个个字符回溯回去了。
这是这个正则表达式存在的第一个问题。另外一个问题是在正则表达式的第三部分,我们发现出现问题的 URL 是有下划线(_)和百分号(%)的,但是对应第三部分的正则表达式里面却没有。这样就会导致前面匹配了一长串的字符之后,发现不匹配,最后回溯回去。这是这个正则表达式存在的第二个问题。
解决方案
明白了回溯是导致问题的原因之后,其实就是减少这种回溯,你会发现如果我在第三部分加上下划线和百分号之后,程序就正常了。
运行上面的程序,立刻就会打印出match!!。
但这是不够的,如果以后还有其他 URL 包含了乱七八糟的字符呢,我们难不成还再修改一遍。肯定不现实嘛!
其实在正则表达式中有这么三种模式:贪婪模式、懒惰模式、独占模式。
在关于数量的匹配中,有 + ? * {min,max} 四种两次,如果只是单独使用,那么它们就是贪婪模式。
如果在他们之后加多一个 ? 符号,那么原先的贪婪模式就会变成懒惰模式,即尽可能少地匹配。但是懒惰模式还是会发生回溯现象的。TODO例如下面这个例子:
text="abbc"regex="ab{1,3}?c"
正则表达式的第一个操作符 a 与 字符串第一个字符 a 匹配,匹配成。于是正则表达式的第二个操作符 b{1,3}? 和 字符串第二个字符 b 匹配,匹配成功。因为最小匹配原则,所以拿正则表达式第三个操作符 c 与字符串第三个字符 b 匹配,发现不匹配。于是回溯回去,拿正则表达式第二个操作符 b{1,3}? 和字符串第三个字符 b 匹配,匹配成功。于是再拿正则表达式第三个操作符 c 与字符串第四个字符 c 匹配,匹配成功。于是结束。
如果在他们之后加多一个 + 符号,那么原先的贪婪模式就会变成独占模式,即尽可能多地匹配,但是不回溯。
于是乎,如果要彻底解决问题,就要在保证功能的同时确保不发生回溯。我将上面校验 URL 的正则表达式的第二部分后面加多了个 + 号,即变成这样:
^([hH][tT]{2}[pP]://|[hH][tT]{2}[pP][sS]://)(([A-Za-z0-9-~]+).)++ --->>> (这里加了个+号)([A-Za-z0-9-~\\/])+$
这样之后,运行原有的程序就没有问题了。
最后推荐一个网站,这个网站可以检查你写的正则表达式和对应的字符串匹配时会不会有问题[1]。
例如我本文中存在问题的那个 URL 使用该网站检查后会提示:catastrophic backgracking(灾难性回溯)。
当你点击左下角的「regex debugger」时,它会告诉你一共经过多少步检查完毕,并且会将所有步骤都列出来,并标明发生回溯的位置。
本文中的这个正则表达式在进行了 11 万步尝试之后,自动停止了。这说明这个正则表达式确实存在问题,需要改进。
但是当我用我们修改过的正则表达式进行测试,即下面这个正则表达式。
^([hH][tT]{2}[pP]:\/\/|[hH][tT]{2}[pP][sS]:\/\/)(([A-Za-z0-9-~]+).)++([A-Za-z0-9-~\\\/])+$
工具提示只用了 58 步就完成了检查。
一个字符的差别,性能就差距了好几万倍。
树义有话说
一个小小的正则表达式竟然能够把 CPU 拖垮,也是很神奇了。这也给平时写程序的我们一个警醒,遇到正则表达式的时候要注意贪婪模式和回溯问题,否则我们每写的一个表达式都是一个雷。
通过查阅网上资料,我发现深圳阿里中心 LAZADA 的同学也在 17 年遇到了这个问题。他们同样也是在测试环境没有发现问题,但是一到线上的时候就发生了 CPU 100% 的问题,他们遇到的问题几乎跟我们的一模一样。有兴趣的朋友可以点击文章[1]
虽然把这篇文章写完了,但是关于 NFA 自动机的原理方面,特别是关于懒惰模式、独占模式的解释方面还是没有解释得足够深入。因为 NFA 自动机确实不是那么容易理解,所以在这方面还需要不断学习加强。欢迎有懂行的朋友来学习交流,互相促进。
原文发布时间为:2018-08-20
本文来自云栖社区合作伙伴“Java技术栈”,了解相关信息可以关注“Java技术栈”。
java 正则表达式验证邮箱格式是否合规 以及 正则表达式元字符
package com.ykmimi.testtest;
/**
* 测试邮箱地址是否合规
* @author ukyor
*
*/
public class EmailTest {
public static void main(String[] args) {
//定义要匹配的Email地址的正则表达式
//其中\w代表可用作标识符的字符,不包括$. \w+表示多个
// \\.\\w表示点.后面有\w 括号{2,3}代表这个\w有2至3个
//牵扯到有些邮箱类似com.cn结尾 所以(\\.\\w{2,3})*后面表示可能有另一个2至3位的域名结尾
//*表示重复0次或更多次
String regex = "\\w+@\\w+(\\.\\w{2,3})*\\.\\w{2,3}";
//声明用于判断的邮箱
String em1 = "aas@.cn";
String em2 = "deadzq@!qq.com";
String em3 = "de@qqcom";
String em4 = "ed123.com";
String em5 = "deadzq@qwq.com";
String em6 = "ukyo@qq.com";
String em7 = "helloworld@123.com";
String em8 = "goldhair@12333.com.cn";
//em9虽然可能没有这样的域名结尾 但符合(\\.\\w{2,3})*\\.\\w{2,3}条件
//更精准的表达式应该把现有国际上域名声明为一个数组 再加以判断
String em9 = "loveinc@ukyo.dd.sss";
//把域名装入域名数组
String[] emailArray = {em1,em2,em3,em4,em5,em6,em7,em8,em9};
//循环判断邮箱是否合规 foreach循环
for(String e : emailArray)
{
//如果其中邮箱元素复合正则表达式 regex 则:
if(e.matches(regex))
{
//输出该邮箱元素 为合规
System.out.println(e+"为合规邮箱输入.");
}
}
}
}
正则表达式元字符
将编程看作是一门艺术,而不单单是个技术。
敲打的英文字符是我的黑白琴键,
思维图纸画出的是我编写的五线谱。
当美妙的华章响起,现实通往二进制的大门即将被打开。
十分钟搞懂正则表达式(上)
引言正则表达式几乎可以在任何语言中进行使用,无论是JS、Java或者是Python或者是其他语言。是不是很羡慕别人的正则表达式写的很6,是不是对于火星文般的一大长串正则表达式很苦恼。本文希望通过对于正则表达式的说明,让大家认识它、接近它最后爱上它。正则表达式基础知识常用正则表达式Java中如何使用正则表达式一、正则表达式基础知识要想学习好正则表达式,我们需要知道到底什么是正则表达式,它是由什么组成的。那到底什么是正则表达式呢?按照自己的理解,正则表达式就是规则,使我们研发人员定义的一种规则,通过这个规则我们可以匹配和筛选符合这个规则的特殊字符串。如下图所示:元字符万物皆有元,正则表达式也不例外,它是由元字符组成的。我们来看下比较常用的元字符,如下表所示:元字符功能.匹配除换行符以外的任意字符\w匹配字母或数字或下划线或汉字\s匹配任意的空白符\d匹配数字\b匹配单词的开始或结束^匹配字符串的开始$匹配字符串的结束有了基础的元字符我们已经可以做一些简单的字符串匹配工作了,举例如下:1、匹配以abc开头的字符串^ abc2、匹配以139开头的手机号码^139\d\d\d\d\d\d\d\d$重复限定符有了基本的元字符可以进行简单的正则匹配,但是写出来的正则表达式不够简洁,有时候会出现很多重复的元字符,如上节第二个手机号码的例子就是如此。所以我们来认识下重复限定符,如下表所示:重复限定符功能*重复零次或更多次+重复一次或更多次?重复零次或一次{n}重复n次{n,m}重复n到m次{n,}重复n次或更多次*?重复任意次,但尽可能少重复+?重复1次或更多次,但尽可能少重复??重复0次或1次,但尽可能少重复{n,m}?重复n到m次,但尽可能少重复{n,}?重复n次以上,但尽可能少重复1、匹配8位数字的QQ号码^\d{8}$2、上节中的以139开头的手机号码^139\d{8}$3、匹配以bn开头,0个或者多个m结尾的字符串^bnm*$注意:重复限定符只对其前面的紧邻的字符起作用。字符分组一般情况下,限定符都是对其左边最近的字符起作用的,如果想要对更多的字符起到限定作用,我们需要使用分组的功能。字符分组功能(exp)匹配exp,并捕获文本到自动命名的组里(?< name >exp)匹配exp,并捕获文本到名称为name的组里,也可以写成(?'name’exp)(?:exp)匹配exp,不捕获匹配的文本,也不给此分组分配组号(?=exp)匹配exp前面的位置(?<=exp)匹配exp后面的位置(?!exp)匹配后面跟的不是exp的位置(?< !exp)匹配前面不是exp的位置(?#comment)这种类型的分组不对正则表达式的处理产生任何影响,用于提供注释让人阅读反义字符反义字符功能\W匹配任意不是字母,数字,下划线,汉字的字符(?< name >exp)匹配exp,并捕获文本到名称为name的组里,也可以写成(?'name’exp)(?:exp)匹配exp,不捕获匹配的文本,也不给此分组分配组号(?=exp)匹配exp前面的位置(?<=exp)匹配exp后面的位置(?!exp)匹配后面跟的不是exp的位置(?< !exp)匹配前面不是exp的位置(?#comment)这种类型的分组不对正则表达式的处理产生任何影响,用于提供注释让人阅读区间限制所谓区间就是对某些统一字符进行一并限定,如[1-9]的含义是匹配1到9的数字。[A-Z]可以限定A到Z的大写字母。或的匹配所谓或的条件就是满足其中的任一条件即为匹配成功。例如:^(139|157)可以匹配以139或者157开头的字符。同时[]也可以表示或的逻辑,例如:[139]改正则表示匹配1或者3或者9。.同时我们需要注意在[]中的^表示非的。[^ab]该表达式代表非a以及b之外的其他任何字符。二、常用正则表达式1、匹配数字^[0-9]*$ //匹配数字
^(0|[1-9][0-9]*)$ //2、匹配字符^[\u4e00-\u9fa5]{0,}$ //匹配汉字
^[A-Za-z]+$ //匹配26个字母3、其他^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$ //匹配邮箱
[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(/.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+/.? //域名三、Java中如何使用正则表达式在Java中的java.util.regex包中,主要提供了用于进行正则模式匹配的工具类。如下图所示:该正则模式匹配包中主要有三类,如下所示:(1)Pattern类:Pattern对象主要用于在开发中创建一个正则表达式。用来进行模式的匹配。可以通过Pattern.complie(String regex)简单工厂方法创建一个正则表达式。(2)Matcher类: Matcher对象是解释模式并对输入字符串执行匹配操作的引擎。 通过解释Pattern对输入的字符串input执行匹配操作的引擎,如Matcher matcher = pattern.matcher(input)。(3)PatternSyntaxException :正则表达式模式中的语法错误异常。
PHP学习笔记之POSIX正则表达式
1 基础知识
正则表达式是一种描述一段文本模式的方法。到目前为止,我们前面所用到过的精确(文字)匹配也是一种正则表达式。例如,前面我们曾搜索过正则表达式的术语,像"shop"和"delivery"。
在PHP中,匹配正则表达式更有点像strstr()匹配,而不像相等比较,因为是在一个字符串的某个位置(如果不指明则可能在字符串中的任何位置)匹配另一个字符串。例如,字符串"shop"匹配正则表达式"shop"。它也可以匹配正则表达式"h"、"ho",等。
除了精确匹配字符外,还可以用特殊字符来指定表达式的元意(meta-meaning)。例如,使用特殊字
符,可以指定一个在字符串开始或末尾肯定存在的模式,该模式的某部分可能被重复,或模式中的字符属于特定的某一类型。此外,还可以按特殊字符的出现来匹
配。接下来,我们将逐个讨论这些变化。
2 字符集和类
使用字符集可以马上给出比精确匹配功能还要强大的正则表达式。字符集可以用于匹配属于特定类型的任何字符;事实上它们是一种通配符。
首先,可以用字符作为一个通配符来代替除换行符(\n)之外的任一个字符。例如,正则表达式:
.at
可以与"cat"、"sat"和"mat"等进行匹配。通常,这种通配符匹配用于操作系统中的文件名匹配。
但是,使用正则表达式,可以更具体地指明希望匹配的字符类型,而且可以指明字符所属的一个集合。在前面的例子中,正则表达式匹配"cat"和"mat",但也可以匹配"#at"。如果要限定它是a到z之间的字符,就可以像下面这样指明:
[a-z]at
任何包含在方括号([])中的内容都是一个字符类——一个被匹配字符所属的字符集合。请注意,方括号中的表达式只匹配一个字符。
我们可以列出一个集合,例如:
[aeiou]
可以用来表示元音子母。
也可以描述一个范围,正如前面用连字符那样,也可以是一个范围集:
[a-zA-Z]
这个范围集代表任何的大小写字母。
此外,还可以用集合来指明字符不属于某个集。例如:
[^a-z]
可以用来匹配任何不在a和z之间的字符。当把脱字符号(^)包括在方括号里面时,表示否。当该符号用在方括号的外面,则表示另外一个意思,我们稍后将详细介绍。
3 重复
通常,读者会希望指明某个字符串或字符类将不止一次地出现。可以在正则表达式中使用两个特殊字符代替。符号“*”表示这个模式可以被重复0次或更多次,符号“+”则表示这个模式可以被重复1次或更多次。这两个符号应该放在要作用的表达式的后面。
例如:
[[:alnum:]]+
表示“至少有一个字母字符”。
4 子表达式
通常,将一个表达式分隔为几个子表达式是非常有用的,例如,可以表示“至少这些字符串中的一个需要精确匹配”。可以使用圆括号来实现,与在数学表达式中的方法一样。
例如:
(very)*large
可以匹配"large"、"very large"、"very very large"等。
5 子表达式计数
可以用在花括号({})中的数字表达式来指定内容允许重复的次数。可以指定一个确切的重复次数({3}表示重复3次),或者一个重复次数的范围({2,4}表示重复2~4次),或是一个开底域的重复范围({2,}表示至少要重复两次)。
例如:
(very){1,3}
表示匹配"very"、"very very"和"very very very"。
6 定位到字符串的开始或末尾
[a-z]模式将匹配任何包含了小写字母字符的字符串。无论该字符串只有一个字符,或者在整个更长的字符串中只包含一个匹配的字符,都没有关系。
也可以确定一个特定的子表达式是否出现在开始、末尾或在两个位置都出现。当要确定字符串中只有要找的单词而没有其他单词出现时,它将相当有用。
脱字符号(^)用于正则表达式的开始,表示子字符串必须出现在被搜索字符串的开始处,字符“$”用于正则表达式的末尾,表示子字符串必须出现在字符串的末尾。
例如,以下是在字符串开始处匹配bob:
^bob
这个模式将匹配com出现在字符串末尾处的字符串:
com$
最后,这个模式将匹配只包含a到z之间一个字符的字符串:
^[a-z]$
7 分支
可以使用正则表达式中的一条竖线来表示一个选择。例如,如果要匹配com、edu或net,就可以使用如下所示的表达式:
com|edu|net
8 匹配特殊字符
如果要匹配本节前面提到过的特殊字符,例如,.、{或者$,就必须在它们前面加一个反斜杠(\)。如果要匹配一个反斜杠,则必须用两个反斜杠(\\)来表示。
在PHP中,必须将正则表达式模式包括在一个单引号字符串中。使用双引号引用的正则表达式将带来一些不必要的复杂性。PHP还使用反斜杠来转义特殊字符——例如反斜杠。
如果希望在模式中匹配一个反斜杠,必须使用两个反斜杠来表示它是一个反斜杠字符,而不是一个转义字符。
同样,由于相同的原因,如果希望在一个双引号引用的PHP字符串中使用反斜杠字符,必须使用两个反斜杠。这可
能会有些混淆,这样要求的结果将是表示一个包含了反斜杠字符的正则表达式的一个PHP字符串需要4个反斜杠。PHP解释器将这4个反斜杠解释成2个。然
后,由正则表达式解释器解析为一个。
$符号也是双引号引用的PHP字符串和正则表达式的特殊字符。要使一个$字符能够在模式中匹配,必须使用“\\\$”。因为这个字符串被引用在双引号中,PHP解释器将其解析为\$,而正则表达式解释器将其解析成一个$字符。
9 在智能表单中应用
在智能表单应用程序中,正则表达式至少有两种用途。第一种用途是在顾客的反馈中查找特定的名词。使用正则表达
式,可以做得更智能一些。使用一个字符串函数,如果希望匹配"shop"、"customer
service"或"retail",就必须做3次不同的搜索。如果使用一个正则表达式,就可以同时匹配所有3个,如下所示:
shop|customer service|retail
第二个用途是验证程序中用户的电子邮件地址,这需要通过用正则表达式来对电子邮件地址的标准格式进行编码。这
个格式中包含一些数字或标点符号,接着是符号“@”,然后是包括文字或数字和字符组成的字符串,后面接着是一个“.”(点号),后面包括文字或数字以连字
符组成的字符串,可能还有更多的点号,直到字符串结束,它的编码如下所示:
^[a-zA-Z0-9_\-.]+@[a-zA-Z0-9\-]+\.[a-zA-Z0-9\-.]+$
子表达式^[a-zA-Z0-9_\-.]+表示“至少由一个字母、数字、下画线、连字符、点号或者这些字符组合为开始的字符串”。请注意,当在一个字符类的开始或末尾处使用点号时,点号将失去其特殊通配符的意义,只能成为一个点号字符。
符号“@”匹配字符“@”。
而子表达式[a-zA-Z0-9\-]+与包含文字数字字符和连字符的主机名匹配。请注意,我们去除了连字符,因为它是方括号内的特殊字符。
字符组合“\.”匹配“.”字符。我们在字符类外部使用点号,因此必须对其转义,使其能够匹配一个点号字符。
子表达式[a-zA-Z0-9\-\.]+$匹配域名的剩下部分,它包含字母、数字和连字符,如果需要还可包含更多的点号直到字符串的末尾。
不难发现,有时一个无效的电子邮件地址也会符合这个正则表达式。找到所有无效电子邮件几乎是不可能的,但是经
过分析,情形将会有所改善。可以按许多不同的方式精化这个表达式。例如,可以列出所有有效的顶级域(TLD)。当对某些对象进行限制的时候,请千万小心,
因为可能排斥1%的有效数据的校验函数比允许出现10%的无效数据的校验函数还要麻烦。
“每个星期读一本书,那么一年就读了50本书” 加油。。。 别给自己太多放弃的理由。
作者:佚名
来源:51CTO
String+正则,实现字符串快速调整 | 带你学《Java语言高级特性》之二十五
上一篇:使用正则必备标记 | 带你学《Java语言高级特性》之二十四了解了正则表达式的相关内容,可以发现正则表达式服务于字符串,而Java中String类也针对正则表达式提供了一系列的便捷方法以供调用,让我们一起来使用正则快速处理字符串吧。
【本节目标】通过阅读本节内容,你将接触到String类针对正则表达式所提供的一系列操作方法,并结合实例代码对其功能有了初步的理解,学会在开发过程中运用这些方法实现字符串的快捷操作。
String类对正则的支持
在进行正则表达式大部分处理的情况下都会基于String类来完成,并且在String类里面提供有如下与正则有关的操作方法:
No
方法名称
类型
描述
01
Public boolean matches(String regex);
普通
将指定字符串进行正则判断
02
public String replaceAll(String regex, String replacement);
普通
替换全部
03
public String replaceFirst(String regex, String replacement);
普通
替换首个
04
public String[] split(String regex);
普通
正则拆分
05
public String[] split(String regex, int limit);
普通
正则指定个数拆分
下面通过一些具体范例来对正则的使用进行说明。范例:实现字符串的替换(删除非字母与数字)
public class JavaAPIDemo {
public static void main(String[] args) throws Exception {
String str = "JILO&*()@#$UISD&*(#$HUK34rwyhui*()@#$*()@#$"; //要判断的数据
String regex = "[^a-zA-Z0-9]+"; //正则表达式
System.out.println(str.replaceAll(regex, ""));//JILOUISDHUK34rwyhui
}
}
范例:实现字符串的拆分
public class JavaAPIDemo {
public static void main(String[] args) throws Exception {
String str = "a1b22c333d4444e55555f666666g";
String regex = "\\d+";
String result[] = str.split(regex);
for (int x = 0 ;x < result.length ; x ++) {
System.out.println(result[x] + "、"); //a、b、c、d、e、f、g、
}
}
}
在正则处理的时候对于拆分和替换的操作相对容易一些,但是比较麻烦的是数据验证的部分。范例:判断一个数据是否为小数,如果是小数则将其变为double类型
public class JavaAPIDemo {
public static void main(String[] args) throws Exception {
String str = "100.32"; //要判断的数据
String regex = "\\d+(\\.\\d+)?"; //正则表达式
System.out.println(str.matches(regex));
}
}
范例:判断一个字符串是否由日期所组成,如果是由日期所组成则将其转为Date类型
public class JavaAPIDemo {
public static void main(String[] args) throws Exception {
String str = "1981-10-15 "; //要判断的数据
String regex = "\\d{4}-\\d{2}-\\d{2}"; //正则表达式
if (str.matches(regex)) {
System.out.println(new SimpleDateFormat("yyyy-MM-dd").parse(str));
}
}
}
需要注意的是,正则表达式无法对里面的内容进行判断,只能够对格式进行判断处理。范例:判断给定的号码是否正确
电话号码:51283346、\\d{7,8};
电话号码:01051283346、(\\d{3,4})?\\d{7,8};
电话号码:(010)-51283346、((\\d{3,4})|(\\(\\d{3,4}\\)-))?\\d{7,8};
public class JavaAPIDemo {
public static void main(String[] args) throws Exception {
String strA = "51283346";
String strB = "01051283346";
String strC = "(010)-51283346";
String regex = "((\\d{3,4})|(\\(\\d{3,4}\\)-))?\\d{7,8}";//正则表达式
System.out.println(strA.matches(regex));
System.out.println(strB.matches(regex));
System.out.println(strC.matches(regex)); //true
}
}
既然已经可以使用正则进行验证了,那么下面就可以利用其来实现一个email地址格式的验证。范例:验证email格式
email的用户名可以由字母、数字、_所组成(不应该使用“_”开头);
email的域名可以由字母、数字、_、-所组成;
email的域名后缀必须是:.cn、.com、.net、.com.cn、.gov;
邮箱正则分析
public class JavaAPIDemo {
public static void main(String[] args) throws Exception {
String str="mldnjava888@mldn.cn";
String regex="[a-zA-Z0-9]\\w+@\\w+\\.(cn|com|net|com\\.cn|gov)";
System.out.println(str.matches(regex));
}
}
以上这几种匹配处理操作是最常用的几种处理形式。
想学习更多的Java的课程吗?从小白到大神,从入门到精通,更多精彩不容错过!免费为您提供更多的学习资源。本内容视频来源于阿里云大学
下一篇:借助regex包完成正则高级操作 | 带你学《Java语言高级特性》之二十六更多Java面向对象编程文章查看此处