深入剖析:正则表达式的奥秘

简介

正则表达式(Regular Expressions)是一种强大的文本处理工具,一种用于匹配文本模式的字符串。它由特定的字符和操作符组成,用于定义一个搜索模式。这些搜索模式可以用于文本搜索、替换、验证和提取数据等多种用途。

以下是一个简单的示例: 

在写用户注册表单时,用户名只允许包含字符、数字、下划线_和连接字符 -,并设置用户名的长度为3~15个字符,这时候就可以使用以下正则表达式:/^[a-z0-9_-]{3,15}$/ 来设定。

因此,这个正则表达式匹配的字符串必须满足以下条件:

  1. 字符串长度在 3 到 15 个字符之间。
  2. 字符串中只能包含小写字母、数字和下划线和连字符。

这种正则表达式通常用于验证用户名、标识符或其他需要满足特定格式的字符串。如果输入的字符串符合上述规则,正则表达式将匹配成功;否则,匹配将失败。

优点

使用正则表达式有许多优点,这解释了为什么它们在各种编程和文本处理领域如此受欢迎。以下是一些主要的优点:

  • 强大的文本模式匹配: 正则表达式允许你定义非常复杂的文本模式,从简单的字符匹配到更复杂的模式,如日期、电子邮件地址、电话号码等。
  • 灵活性: 正则表达式非常灵活,可以应对多种文本处理需求。您可以轻松地自定义匹配模式,以满足特定的要求。
  • 广泛的应用领域: 正则表达式可以应用于各种领域,包括文本搜索、数据验证、日志分析、数据提取、编程语言中的模式匹配等。
  • 快速和高效: 正则表达式引擎经过高度优化,可以快速执行匹配操作,这使它们成为处理大量文本数据的理想工具。
  • 一次性批处理: 正则表达式可以同时处理多个匹配,而无需迭代,从而节省了时间和资源。
  • 文本替代: 正则表达式不仅可以用于匹配,还可以用于替代文本。这使得在文本中进行搜索和替换操作非常容易。
  • 标准化: 正则表达式是一种标准化的文本匹配工具,因此在不同编程语言和工具中的语法基本相同,使得知识可迁移性很强。
  • 表达力强: 正则表达式支持逻辑运算、分组、捕获等高级功能,允许构建复杂的匹配模式。
  • 数据清洗: 正则表达式可以用于清洗和转换数据,将其从一个格式转换为另一个格式。
  • 自然语言处理: 在自然语言处理(NLP)任务中,正则表达式可用于文本分析、分词和模式匹配,从而帮助处理文本数据。

应用领域

正则表达式可以应用于许多领域和各种编程语言。以下是一些常见的应用领域:

  • 文本搜索和替换: 正则表达式用于在文本中搜索和替换特定模式的字符串。这在文本编辑器、代码编辑器和命令行工具中非常常见。
  • 数据验证: 正则表达式可用于验证用户输入的数据是否符合特定格式,如电子邮件地址、电话号码、日期、密码等。
  • 日志分析: 系统管理员和开发人员可以使用正则表达式来分析大型日志文件,以查找特定事件、错误或信息。
  • 数据提取: 在文本数据中提取信息是正则表达式的常见用途。这可以用于从文本中提取网址、价格、标签、电话号码等。
  • 编程语言中的模式匹配: 编程语言如Python、Java和JavaScript允许使用正则表达式进行模式匹配和操作。这在字符串处理和文本解析中非常有用。
  • 网页抓取和爬虫: 网络爬虫可以使用正则表达式来定位和提取网页上的数据,如链接、标题、日期等。
  • 数据清洗: 在数据分析中,正则表达式可用于清理和转换数据,以使其更易于分析。
  • 路由和URL匹配: Web框架和路由系统使用正则表达式来匹配URL,以确定哪个控制器或页面应该处理请求。
  • 密码策略: 正则表达式可用于定义密码策略,要求密码满足特定的复杂性和长度要求。
  • 自然语言处理: 在自然语言处理(NLP)中,正则表达式可以用于文本分析、分词和情感分析等任务。
  • 数据替换和格式化: 正则表达式可用于将数据转换为特定格式,如日期格式化、数字格式化等。
  • 日程表处理: 正则表达式可以用于解析和处理日期、时间和日程表数据。
  • 网络安全: 正则表达式可用于检测恶意软件、网络入侵和安全威胁。

不同命令或环境下对正则表达式的支持: 

命令或环境.[ ]^$\( \)\{ \}?+|( )
vi     
Visual C++     
awk 
sed    
delphi 
python
java√ √ 
javascript 
php     
perl 
C#  


匹配规则

正则表达式的匹配规则基于特殊字符和模式构建,这些字符和模式指定了要匹配的文本模式。

基本的模式匹配

模式指的是正则表达式中定义的文本模式,是正则表达式最基本的元素,用于搜索、匹配和操作文本。这个模式是由特殊字符、元字符和普通字符组成的,它规定了你希望在文本中找到的具体模式。例如:

/^once/

这个模式包含一个特殊字符 ^,表示该模式只匹配以 once 开头的字符串。例如该模式与字符串 "once upon a time" 匹配,与 "There once was a man from NewYork" 不匹配。

正如如 ^ 符号表示开头一样,$ 符号用来匹配那些以给定模式结尾的字符串。

/bucket$/

这个模式与 "Who kept all of this cash in a bucket" 匹配,与 "buckets" 不匹配。字符 ^ 和 $ 同时使用时,表示精确匹配(字符串与模式一样)。例如:

/^bucket$/

只匹配字符串 "bucket"。如果一个模式不包括 ^ 和 $,那么它与任何包含该模式的字符串匹配。

例如模式/once/与字符串 “ There once was a man from NewYork Who kept all of his cash in a bucket. ” 是匹配的。该模式中的字母是字面的字符,表示该字母本身。数字也是一样的。

其他一些稍微复杂的字符,如标点符号和白字符(空格、制表符等),要用到转义序列。所有的转义序列都用反斜杠 \ 打头。制表符的转义序列是 \t。如果要检测一个字符串是否以制表符开头,可以用模式:^\t 。

类似的,用 \n 表示"新行",\r 表示回车。其他的特殊符号,可以用在前面加上反斜杠,如反斜杠本身用 \\ 表示,句号 . 用 \. 表示,以此类推。

字符类

有时用正则表达式来验证用户的输入。当用户提交一个输入以后,要判断输入的电话号码、地址、EMAIL 地址、信用卡号码等是否有效,用普通的基于字面的字符是不够的。所以要用一种更自由的描述我们要的模式的办法,它就是字符类。

例如,要建立一个表示所有元音字符的字符类,就把所有的元音字符放在一个方括号里:

[AaEeIiOoUu]

注意:这个模式与任何元音字符匹配,但只能表示一个字符。

用连字号可以表示一个字符的范围(同样也只表示一个字符)。如:

  • [a-z]           // 匹配所有的小写字母 
  • [a-zA-Z]     // 匹配所有的字母 
  • [0-9\.\-]      // 匹配所有的数字,句号和连字符

:在正则表达式中,小数点(.)和连字符(-)具有特殊含义,它们通常用作元字符,表示匹配任何字符(小数点)或指定字符范围(连字符)。如果你想要匹配这些字符的字面意义,而不是使用它们的特殊含义,需要对它们进行转义,即在它们前面加上反斜杠(\)。

如果要匹配一个由一个小写字母和一位数字组成的字符串,比如 "z2"、"t6" ,用这个模式:

/^[a-z][0-9]$/

尽管 [a-z] 代表 26 个字母的范围,但在这里它只能与第一个是小写字母的字符串匹配。

^ 表示字符串的开头,但当它在一组方括号里使用 ^ 时,就表示""或"排除"的意思,常常用来剔除某个字符。还用前面的例子,现在要求第一个字符不能是数字,而第二个字符是数字,比如 "&5"、"g7":

/^[^0-9][0-9]$/

匹配的次数

目前为止,你已经知道如何去匹配一个字母或数字,但通常情况下,需要匹配一个或多个字符或数字,可以使用跟在字符或字符类后面的花括号 {N} 来确定前面的内容的重复匹配的次数。例如:

a{3}精确匹配字符 "a" 重复出现 3 次。它只匹配 "aaa",不匹配其他重复次数的 "a"。
a{3,}匹配字符 "a" 重复出现的次数至少为 3 次或更多。这意味着它将匹配 "aaa"、"aaaa"、
"aaaaa" 等任何 "a" 重复次数大于或等于 3 次的情况。
a{1,3}匹配字符 "a" 重复出现的次数在 1 到 3 次之间。这意味着它将匹配 "a"、"aa" 或 "aaa",
但不会匹配没有 "a" 或重复次数超过 3 次的情况。

这些例子描述了花括号的三种不同的用法:

  •  {N}:匹配字符或字符类,恰好 N 次 ;
  •  {N,}:匹配字符或字符类重复出现的次数至少为 N 次或更多 ;
  •  {N,M}:匹配字符或字符类重复出现的次数在 N 到 M 次之间。

可以把模式扩展到更多的单词或数字:

  • ^[a-zA-Z0-9_]{1,}$:匹配所有包含一个以上的字母、数字或下划线的字符串 
  • ^[1-9][0-9]{0,}$:匹配所有的正整数 

当然这并不能从技术上降低正则表达式的复杂性,但可以使它们更容易阅读。


正则表达式的模式

正则表达式是由字面值字符(例如字符 a 到 z)以及特殊字符(称为"元字符")组成适当的文字模式,用于定义要匹配的模式,复杂程度取决于匹配模式的复杂性。模式描述的是在搜索文本时要匹配的一个或多个字符串。

字面值字符

正则表达式模式中的字面值字符,即普通字符,是指那些不具备特殊含义、没有显式指定为元字符的所有可打印和不可打印字符,它们会与输入的文本字符进行精确匹配。字面值字符通常是正则表达式模式的基本构建块,用于匹配特定字符或字符序列。以下是一些常见的字面值字符:

  • 字母和数字: 字母和数字字符通常会与自身匹配。例如,正则表达式中的字符 "a" 将精确匹配文本中的 "a"。
  • 空格: 空格字符通常用于匹配文本中的空格。
  • 标点符号: 大多数标点符号(如句号、逗号、感叹号等)也是字面值字符,它们与输入文本中的相应字符进行匹配。例如,字符 "." 将精确匹配文本中的句号。
  • 特殊字符的转义: 一些特殊字符,如 $、(、)、[、]、.、*、+、? 等,在正则表达式中具有特殊含义。如果您想匹配这些字符本身,需要在它们前面加上反斜杠 \ 进行转义。例如,要匹配文本中的 $ 字符,可以使用 \ 进行转义,写成 \$。
  • 非打印字符的转义序列: 非打印字符是一组特殊字符,通常不可见,如换行、回车、制表符等。这些字符在文本中存在,但通常不会以字面形式可见,而是用特殊的转义序列表示。

以下是一些非打印字符的示例,以及它们在正则表达式和其他文本处理上下文中的转义序列:

  • 换行字符(\n):在正则表达式中,\n 用于匹配文本中的换行字符。例如,"Hello\nWorld" 匹配包含换行的字符串。
  • 回车字符(\r):用于匹配回车字符。例如,"Line1\rLine2" 匹配包含回车的字符串。
  • 制表符(\t):用于匹配制表符。例如,"Value1\tValue2" 匹配包含制表符的字符串。
  • 垂直制表符(\v):用于匹配垂直制表符。例如,"Item1\vItem2" 匹配包含垂直制表符的字符串。
  • 换页字符(\f):用于匹配换页字符。例如,"Page1\fPage2" 匹配包含换页字符的字符串。

这些转义序列允许你在正则表达式和其他文本处理上下文中匹配、替换或操作非打印字符,尽管这些字符通常是不可见的。

  • Unicode字符:正则表达式也支持匹配特定的Unicode字符,例如,\uXXXX 可以用于匹配Unicode编码为XXXX的字符。 

特殊字符(元字符)

正则表达式中的特殊字符是那些具有特殊含义的字符,它们不会与输入文本中的相同字符进行精确匹配,而是用于构建匹配模式或执行特定的匹配操作。

许多元字符要求在试图匹配它们时特别对待。若要匹配这些特殊字符,必须首先使字符"转义",即,将反斜杠字符\ 放在它们前面。如 abc*b 中的 *,表示任何字符串。如果要查找字符串中的 * 符号,则需要对 * 进行转义,即abc\*b 。

基本字符匹配

  • \:转义字符,用于匹配特殊字符本身,或标记为一个原义字符、或一个向后引用、或一个八进制转义符。例如,'n' 匹配字符 "n"。'\n' 匹配一个换行符。序列 '\\' 匹配 "\" 而 "\(" 则匹配 "("。
  • .:匹配除换行符之外的任何字符。但在字符类 [.] 中,只会匹配字符 . 
  • |:用于创建分支结构,匹配多个模式中的一个。例如,'z|food' 能匹配 "z" 或 "food"。'(z|f)ood' 则匹配 "zood" 或 "food"。
  • \s:表示匹配空白字符(Whitespace Character),包括空格、制表符、换行符和其他空白字符。
  • \S:匹配任何非空白字符。不包括换行。
  • \w:表示匹配单词字符(Word Character),通常包括字母、数字和下划线。
  • \W:匹配非单词字符(Non-Word Character),等效于 [^A-Za-z0-9_]。用于匹配非单词字符。
  • \d:匹配数字字符(Digit Character),等效于 [0-9]。用于匹配数字。
  • \D:匹配非数字字符(Non-Digit Character),等效于 [^0-9]。用于匹配非数字字符。
  • \b:匹配单词边界(Word Boundary)。用于在单词边界位置匹配,不匹配字符本身。
  • \B:匹配非单词边界(Non-Word Boundary)。用于在非单词边界位置匹配,不匹配字符本身。
  • \f:匹配换页字符(Form Feed),通常用于在文本中进行页面分隔。
  • \n:匹配换行字符(Line Feed),通常表示文本中的行结束。
  • \r:匹配回车字符(Carriage Return),通常表示文本中的行的起始或行结束。
  • \t:匹配制表符(Tab),用于表示文本中的制表符。
  • \v:匹配垂直制表符(Vertical Tab),通常用于在文本中进行垂直对齐。

限定符(量词)

限定符通常也被称为量词,用于整个范围表达式之后。用来指定正则表达式的前一个元素(字符、字符类、子表达式等)的匹配次数,以控制匹配的数量。{ 和 } 标记范围表达式的开始和结束位置。

  • *:匹配前面的模式(子表达式)零次或多次。
  • +:匹配前面的模式一次或多次。
  • ?:匹配前面的模式零次或一次,例如,do(es)? 可以匹配 "do" 、 "does"、或 "doxy" 中的 "do" ,? 等价于 {0,1}。
  • ?:紧跟在其他限制符后面时,指明匹配模式为非贪婪。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,'o+?' 将匹配字符串 "oooo" 的单个 "o",而 'o+' 将匹配所有 'o'。
  • {n}:匹配前面的模式恰好 n 次,n 是一个非负整数。例如,o{2} 不能匹配 "Bob" 中的 o,但是能匹配 "food" 中的两个 o。
  • {n,}:匹配前面的模式至少 n 次,n 是一个非负整数。例如,o{2,} 不能匹配 "Bob" 中的 o,但能匹配 "foooood" 中的所有 o。o{1,} 等价于 o+。o{0,} 则等价于 o*。
  • {n,m}:匹配前面的模式至少 n 次且不超过 m 次,m 和 n 均为非负整数,其中 n <= m。例如,o{1,3} 将匹配 "fooooood" 中的前三个 o。o{0,1} 等价于 o?。请注意在逗号和两个数之间不能有空格。
贪婪和非贪婪

在正则表达式中,"贪婪"(Greedy)和"非贪婪"(Non-Greedy)是描述匹配模式的两种行为方式。它们影响匹配重复的模式时的行为,尤其是在使用限定符(例如 *、+、?、{n,})时。

  • 贪婪匹配(Greedy Matching):默认情况下,正则表达式是贪婪的。这意味着它会尽可能多地匹配字符,以满足模式。例如,对于正则表达式 a.*b 和字符串 "axxxbyyybz",贪婪匹配将匹配"axxxbyyyb",而不是只匹配 "axxxb"。
  • 非贪婪匹配(Non-Greedy Matching):也称为懒惰匹配,使用 ? 后缀来实现,例如 *?、+?、??、{n,}?。这表示匹配将尽可能少地匹配字符,以满足模式。例如,对于正则表达式 a.*?b 和字符串 "axxxbyyybz",非贪婪匹配将只匹配 "axxxb",而不是整个字符串。

非贪婪匹配在某些情况下非常有用,特别是当你需要匹配尽可能短的内容或在文本中找到最小的匹配项时。贪婪匹配通常用于匹配尽可能多的内容。


定位符(边界匹配)

定位符用于指定匹配发生的位置,而不是匹配字符本身。定位符还允许你在文本中定义位置,使正则表达式匹配在一个单词的内部、开头或结尾,以便更精确地匹配所需的文本,以满足特定的匹配需求,而不一定匹配具体的字符。以下是一些常见的正则表达式定位符:

  • ^:在模式的开头使用 ^,表示匹配字符串的开头。例如,^abc 匹配以 "abc" 开头的字符串。
  • $:在模式的末尾使用$,表示匹配字符串的结尾。例如,xyz$ 匹配以 "xyz" 结尾的字符串。
  • \b:匹配单词边界。单词边界通常是单词字符(字母、数字、下划线)和非单词字符之间的位置。例如,\bword\b 匹配 "word" 作为一个单词的出现,不匹配 "subword" 中的 "word"。
  • \B:匹配非单词边界。与 \b 相反,\B 匹配不是单词边界的位置。例如,\Bword\B 匹配 "subword" 中的 "word",但不匹配 "word" 作为一个单独的单词。

注意:正则表达式中允许在紧靠换行或单词边界的前面或后面使用定位符,如 ^(行的开始)、$(行的结束)以及 \b(单词边界)。这些定位符在正则表达式中是合法的,并且常常用于匹配特定位置的文本。然而,像 ^* 这样的表达式是无效的,因为 ^ 是一个定位符,用于匹配行的开始,而 * 是一个限定符,用于匹配前面的模式零次或多次。将它们组合在一起没有明确定义,因此不是有效的正则表达式,必须按照正则表达式的语法规则来组合和使用它们。

示例:搜索章节标题。章节标题通常出现行的开始处,又出现在同一行的结尾,且是该行唯一存在的文本。下面的正则表达式能确保只匹配章节而不匹配交叉引用。使用定位点,创建只匹配一行文本的开始和结尾的正则表达式,就可做到这一点。

/^Chapter [1-9][0-9]{0,1}$/

示例:匹配单词边界。单词边界是单词和空格之间的位置,非单词边界是其他任何位置。下面的表达式匹配单词 Chapter 的开头三个字符,因为这三个字符出现在单词边界后面:

/\bCha/

\b 字符位置的不同表示不同的含义:

位于字符串的开始,它在单词的开始处查找匹配项;

位于字符串的结尾,它在单词的结尾处查找匹配项。

例如,下面的表达式匹配单词 Chapter 中的字符串 ter,因为它出现在单词边界的前面:

/ter\b/

对于 \B 非单词边界运算符,不可以匹配单词的开头或结尾,下面的表达式匹配 Chapter 中的字符串 apt,但不匹配 aptitude 中的字符串 apt:

/\Bapt/

字符类

字符类是一组字符或字符范围,用于指定匹配的字符集合,使用 [ ] 来定义字符类。范围表达式是字符类中的一种方式,使用连字符 - 指定一个范围内的字符,而不必逐个列出每个字符。例如,正则表达式 [a-z] 表示匹配小写英文字母 a 到 z 之间的任何一个字符。

  • [  ]:用于创建字符类,匹配字符集合中的任何一个字符。
  • [^ ]:匹配除了括号内的字符以外的任意一个字符。例如,[^abc] 匹配除了字符 "a"、"b" 或 "c" 以外的任意字符。

基本字符类:

  • [abc]:匹配字符集合中的任何一个字符,即匹配 "a"、"b" 或 "c"。

字符范围:

  • [0-9]:匹配任何数字字符。
  • [a-z]:匹配任何小写字母。
  • [A-Z]:匹配任何大写字母。
  • [a-zA-Z]:匹配任何字母,包括小写和大写。
  • [a-zA-Z0-9]:匹配任何英文字母或数字字符

字符类的否定:

  • [^abc]:匹配除了 "a"、"b" 和 "c" 之外的任何字符。
  • [^0-9]:匹配非数字字符。
  • [^A-Za-z]:匹配非字母字符。

字符类中的特殊字符:

  • [.]:匹配句号字符。
  • [\^]:匹配插入符字符。
  • [-]:匹配连字符字符。

分组

正则表达式中的分组,是指使用括号 ( ) 将模式的一部分子表达式括起来,分组在一起,以便对其应用修饰符、重复次数或后续引用,以便更灵活地控制匹配行为和提取匹配的子字符串。

以下是正则表达式分组的常见用途:

捕获组

捕获组是最常见的分组类型。它们使用括号将子表达式括起来,以便将匹配的文本保存到一个单独的组中,以便稍后引用或进行后续处理。捕获组具有捕获功能,可以捕获匹配的子字符串,以备后续引用或处理。

每个捕获组都有一个编号,通常从1开始。可以使用捕获组的编号来引用捕获的子字符串。例如:

正则表达式:(\d{3})-(\d{2})
匹配示例: "123-45"
捕获组:Group 1 包含 "123",Group 2 包含 "45"

非捕获分组

非捕获组也使用括号,但它们以 (?: ) 的形式表示。非捕获组用于分组子表达式,但不会将匹配的文本保存到单独的组中,从而提高正则表达式的性能。非捕获组通常用于模式分组,而不需要后续引用或处理匹配。例如:

正则表达式:(?:\d{3})-(\d{2})
匹配示例: "123-45"
非捕获组:不会创建额外的组,仅捕获 "45"

后向引用

分组允许在正则表达式中引用先前捕获的文本。这对于替换文本,或在模式中多次使用相同的子字符串非常有用。

在正则表达式模式中,可以使用 \ 加捕获组编号来引用已捕获的子字符串,以便在模式中再次使用它们。例如 \1、\2,其中 \1 引用捕获组 1 中的内容,\2 引用捕获组 2 中的内容,以此类推。例如:

正则表达式:<(\w+)>.+<\/\1>
匹配示例: "<div>内容</div>"
后向引用:\1 引用第一个捕获组,即 (\w+) 匹配的标签名,以确保开标签和闭标签匹配。


断言

断言是正则表达式中的一种特殊语法,它用于在匹配模式中添加条件,以约束匹配的文本。断言不会捕获实际的文本,而是对文本的上下文进行约束,以确保匹配满足特定的条件。

有两种主要类型的断言:

正向断言(Lookahead Assertion):正向断言用于指定匹配必须满足的条件,但不包括条件本身。常见的正向断言包括:

  • 正向先行断言 (?=...),表示匹配必须满足括号内的条件,但不包括条件本身。示例:匹配: "apple" ,后面紧跟着 "pie" 的文本。
apple(?=pie)
  • 正向后行断言 (?<=...),表示匹配必须前面是括号内的条件,但不包括条件本身。示例:匹配前面紧跟着 "good" 的单词 "job"。
(?<=good )job

负向断言(Negative Lookahead Assertion):负向断言用于指定匹配不能满足的条件。常见的负向断言包括:

  • 负向先行断言 (?!...),表示匹配不能满足括号内的条件。示例:匹配后面不跟着文本 "pie" 的 "apple" 。
apple(?!pie)
  • 负向后行断言 (?<!...),表示匹配不能前面是括号内的条件。示例:匹配前面不是 "bad " 的单词 "apple"。
(?<!bad )apple

修饰符(标记)

正则表达式的修饰符,也称为标志,用于修改正则表达式的匹配行为的特殊标记,通常以字母的形式出现在正则表达式的末尾,并影响匹配的方式。

标记不写在正则表达式里,标记位于表达式之外,格式如下:

/pattern/flags

以下是一些常见的正则表达式修饰符:

  • i(不区分大小写):当启用这个修饰符时,正则表达式将不区分字母的大小写。例如,/apple/i 匹配 "apple"、"Apple" 和 "aPpLe" 等。
  • g(全局匹配):启用全局匹配后,正则表达式将尝试找到所有匹配而不仅仅是第一个匹配。例如,/abc/g 将匹配 "abc abc abc" 中的所有 "abc"。
  • m(多行匹配):启用多行匹配后,正则表达式中的 ^ 和 $ 将分别匹配行的开头和行的结尾,而不仅仅是整个字符串的开头和结尾。例如,/^abc/m 匹配 "abc def\nabc ghi" 两行的开头的 "abc"。
  • s(单行匹配):启用单行匹配后,点号 . 匹配任何字符,包括换行符 \n。例如,/a.b/s 可以匹配 "a\nb", "a b", "a\tb"。
  • u(Unicode匹配):启用 Unicode 匹配后,正则表达式将支持 Unicode 字符,并允许匹配各种语言的字符。例如,/\p{Sc}/u 可以匹配各种货币符号,如 "$"、"€" 和 "₣"。
  • y(粘性匹配):启用粘性匹配后,匹配从字符串的当前位置开始,而不是从头开始。例如,在 "abc abc abc" 中,匹配了第一个 "abc" 后,/abc/y 将继续查找下一个 "abc",而不会重新从字符串的开头开始匹配。

这些修饰符可以单独使用,也可以组合使用,以根据需要修改正则表达式的匹配行为。修饰符在不同编程语言和正则表达式引擎中的语法可能会有所不同,因此确保查阅特定语言或引擎的文档以了解如何正确使用它们。


运算符优先级

正则表达式中的运算符优先级指的是不同正则表达式元素的匹配顺序和结合性。了解正则表达式的运算符优先级很重要,因为它们会影响匹配的行为。正则表达式从左到右进行计算,以下是常见正则表达式运算符和元素的优先级,按从高到低的顺序:

  1. 转义符号:\,用于转义特殊字符,如 \., \*。
  2. 圆括号:( 和 ),用于分组和捕获。
  3. 字符类和字符范围:[ ],用于指定字符集。
  4. 量词:*, +, ?, {n}, {n,}, {n,m},用于指定匹配次数。
  5. 定位符:^, $,用于匹配字符串的开始和结束。
  6. 逻辑或:|,用于在多个模式之间选择一个。
  7. 断言:(?=...), (?!...), (?<=...), (?<!...),用于条件测试。

这个优先级顺序是默认情况下的,但你可以使用括号来显式指定运算的顺序,以满足特定匹配需求。括号可以用于分组操作,从而改变运算符的结合性。


实例

实例1:查找文本中重复的单词

以此句为例:

This Is is the Top-Rated Tourist Attraction in in the U.S.—and It’s Completely Free free!

下面的正则表达式使用单个子表达式来实现这一点:

/\b([a-z]+) \1\b/igm

正则表达式 /\b([a-z]+) \1\b/igm 的目的是匹配连续重复的单词。它的各部分含义如下:

  • \b:匹配单词边界,确保匹配的单词是整个单词,而不是其它单词的一部分,诸如 "is issue" 或 "This is" 之类。
  • ([a-z]+):这是一个捕获组,用于匹配一个或多个小写字母字符。
  • 空格字符 " ":匹配一个空格,相邻单词间的空格。
  • \1:这是后向引用,引用前面捕获的内容,即([a-z]+)捕获的内容。

正则表达式模式中的 i、g 和 m 是修饰符(标记),它们表示以下内容:

  • i:不区分大小写,允许匹配小写和大写字母。
  • g:全局匹配,匹配所有符合条件的模式,而不仅仅是第一个。
  • m:多行匹配,允许匹配跨行的文本。

对于输入字符串 "This Is is the Top-Rated Tourist Attraction in in the U.S.—and It’s Completely Free free!",它将匹配 "is is" 和 "in in" 和 “Free free”。

实例2:将 URI 分解为其组件

URI 是通用资源标识符(Uniform Resource Identifier)的缩写,用于标识互联网上资源的字符串,包括但不限于网页、文件、数据库条目、电子邮件地址和其他资源。URI 的主要目的是唯一标识和定位资源,以便浏览器、网络应用程序和其他工具可以访问这些资源。

将下面的 URI 分解为协议(ftp、http 等等)、域地址和页/路径:

https://www.runoob.com:80/html/html-tutorial.html

下面的正则表达式提供该功能:

/(\w+):\/\/([^/:]+)(:\d*)?([^# ]*)/

以下是每个捕获组在此 URL 中的匹配:

  • (\w+):匹配了 "https",这是URL的协议部分。
  • :\/\/:匹配了 "://",URL中的分隔符,表示协议和主机之间的分隔。斜杠字符 / 是一个特殊字符,通常用作正则表达式的开始和结束标记。因此,匹配斜杠字符 / 本身,需要对其进行转义,即使用反斜杠 \ 来转义它,写作 \/。
  • ([^/:]+):匹配了 "www.runoob.com",这是主机名部分。它匹配主机名,但不包括端口号。字符类 [^/:]+ 匹配一个或多个字符,这些字符既不是冒号 : 也不是斜杠 /。字符类 [^...] 表示匹配除括号中列出的字符之外的任何字符。
  • (:\d*)?:匹配了 ":80",这是可选的端口号部分。这个部分包括冒号和数字字符,表示端口号。在此示例中,端口号为 80。
  • ([^# ]*):匹配了 "/html/html-tutorial.html",这是路径部分,表示资源的位置和文件名。这个部分匹配除井号 "#" 和空格之外的所有字符序列。

正则表达式成功地将 URL https://www.runoob.com:80/html/html-tutorial.html 分成了协议、主机、端口和路径组件,以便后续处理和解析。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/180779.html

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

相关文章

canal+es+kibana+springboot

1、环境准备 服务器&#xff1a;Centos7 Jdk版本&#xff1a;1.8 Mysql版本&#xff1a;5.7.44 Canal版本&#xff1a;1.17 Es版本&#xff1a;7.12.1 kibana版本&#xff1a;7.12.1 软件包下载地址&#xff1a;链接&#xff1a;https://pan.baidu.com/s/1jRpCJP0-hr9aI…

【Python语言】序列(列表,元组,字符串)切片操作

目录 序列切片操作 1.1 对list进行切片&#xff0c;从1开始&#xff0c;到5结束&#xff0c;步长为1 [ 1 : 5 ] 1.2 对tuple进行切片&#xff0c;从头开始&#xff0c;到最后结束&#xff0c;步长为1 [ : ] 1.3 对str进行切片&#xff0c;从头开始&#xff0c;到最…

『精』Vue 组件如何模块化抽离Props

『精』Vue 组件如何模块化抽离Props 文章目录 『精』Vue 组件如何模块化抽离Props一、为什么要抽离Props二、选项式API方式抽离三、组合式API方式抽离3.1 TypeScript类型方式3.2 文件分离方式3.3 对文件分离方式优化 参考资料&#x1f498;推荐博文&#x1f357; 一、为什么要抽…

Cordova插件开发二:高精度定位之卫星数据解析

文章目录 1.最终效果预览2.坐标获取方法3.在公共类中封装获取坐标的通用方法4.插件js中封装startGeoLocation方法5.插件主界面封装的方法1.最终效果预览 2.坐标获取方法 let obj = Object.assign({}, this.mapConfig.mapLocationObj)obj.isKeepCallBack = falselet res = await…

探索无限可能:APITable免费开源多维表格与可视化数据库远程访问的魅力

APITable免费开源的多维表格与可视化数据库公网远程访问 文章目录 APITable免费开源的多维表格与可视化数据库公网远程访问前言1. 部署APITable2. cpolar的安装和注册3. 配置APITable公网访问地址4. 固定APITable公网地址 前言 vika维格表作为新一代数据生产力平台&#xff0c…

代码生成器

Easycode Entity ##导入宏定义 $!{define.vm}##保存文件&#xff08;宏定义&#xff09; #save("/entity", ".java")##包路径&#xff08;宏定义&#xff09; #setPackageSuffix("entity")##自动导入包&#xff08;全局变量&#xff09; $!{au…

半导体工厂将应用哪些制造创新技术?

半导体工厂是高科技产业的结晶&#xff0c;汇聚了世界上最新的技术。 在半导体的原料硅晶片上绘制设计图纸&#xff0c;不产生误差&#xff0c;准确切割并包装&#xff0c;然后用芯片生产出我们使用的电脑、智能手机、手表等各种电子产品。绝大多数半导体厂都采用一贯的工艺&a…

android display 杂谈(三)WMS

用来记录学习wms&#xff0c;后续会一点一点更新。。。。。。 代码&#xff1a;android14 WMS是在SystemServer进程中启动的 在SystemServer中的main方法中&#xff0c;调用run方法。 private void run() { // Initialize native services.初始化服务&#xff0c;加载andro…

【PyTorch实战演练】AlexNet网络模型构建并使用Cifar10数据集进行批量训练(附代码)

目录 0. 前言 1. Cifar10数据集 2. AlexNet网络模型 2.1 AlexNet的网络结构 2.2 激活函数ReLu 2.3 Dropout方法 2.4 数据增强 3. 使用GPU加速进行批量训练 4. 网络模型构建 5. 训练过程 6. 完整代码 0. 前言 按照国际惯例&#xff0c;首先声明&#xff1a;本文只是我…

《Pytorch新手入门》第二节-动手搭建神经网络

《Pytorch新手入门》第二节-动手搭建神经网络 一、神经网络介绍二、使用torch.nn搭建神经网络2.1 定义网络2.2 torch.autograd.Variable2.3 损失函数与反向传播2.4 优化器torch.optim 三、实战-实现图像分类(CIFAR-10数据集)3.1 CIFAR-10数据集加载与预处理3.2 定义网络结构3.3…

2.Docker基本架构简介与安装实战

1.认识Docker的基本架构 下面这张图是docker官网上的&#xff0c;介绍了整个Docker的基础架构&#xff0c;我们根据这张图来学习一下docker的涉及到的一些相关概念。 1.1 Docker的架构组成 Docker架构是由Client(客户端)、Docker Host(服务端)、Registry(远程仓库)组成。 …

【Python基础】Python编程入门自学笔记,基础大全,一篇到底!

&#x1f4e2;&#xff1a;如果你也对机器人、人工智能感兴趣&#xff0c;看来我们志同道合✨ &#x1f4e2;&#xff1a;不妨浏览一下我的博客主页【https://blog.csdn.net/weixin_51244852】 &#x1f4e2;&#xff1a;文章若有幸对你有帮助&#xff0c;可点赞 &#x1f44d;…

Dubbo捕获自定义异常

一.问题描述 Dubbo远程服务提供者抛出的自定义异常无法被消费方正常捕获&#xff0c;消费方捕获的自定义异常全部变成RuntimeException&#xff0c;使用起来很不方便。 二.原因分析 相关源码 /** Licensed to the Apache Software Foundation (ASF) under one or more* con…

SpringBoot----自定义Start(自定义依赖)

一&#xff0c;为什么要定义Start 向阿里云OSS如果我们要引入的话很麻烦&#xff0c;所以我们可以自定义一些组件&#xff0c; 然后我们只需要在pom文件中引入对应的坐标就可以 二&#xff0c;怎么定义&#xff08;以阿里云OSS为例&#xff09; 1&#xff0c; 定义两个组件模块…

时间序列聚类的直观方法

一、介绍 我们将使用轮廓分数和一些距离度量来执行时间序列聚类实验&#xff0c;同时利用直观的可视化&#xff0c;让我们看看下面的时间序列&#xff1a; 这些可以被视为具有正弦、余弦、方波和锯齿波的四种不同的周期性时间序列 如果我们添加随机噪声和距原点的距离来沿 y 轴…

DeepSORT多目标跟踪——算法流程与源码解析

一、目标检测与目标追踪 1. 目标检测 在目标检测任务中&#xff0c;主要目标是识别图像或视频帧中存在的物体的位置和类别信息。这意味着目标检测算法需要定位物体的边界框&#xff08;Bounding Box&#xff09;并确定每个边界框内的物体属于哪个类别&#xff08;如人、汽车、…

Panda3d 相机控制

Panda3d 相机控制 文章目录 Panda3d 相机控制Panda3d中的透视镜头和垂直镜头透视镜头垂直镜头 Panda3d 中用代码控制相机的移动用键盘控制相机的移动用鼠标控制相机的移动 Panda3d 把相机也当做是一个 PandaNode&#xff0c;因此可以向操作其他节点对其进行操作。 真正的相机是…

(自适应手机端)响应式新闻博客知识类pbootcms网站模板 自媒体运营博客网站源码下载

(自适应手机端)响应式新闻博客知识类pbootcms网站模板 自媒体运营博客网站源码下载 带后台系统PbootCMS内核开发的网站模板&#xff0c;该模板适用于新闻博客网站、自媒体运营网站等企业&#xff0c;当然其他行业也可以做&#xff0c;只需要把文字图片换成其他行业的即可&#…

怎样做好金融投资翻译

我们知道&#xff0c; 金融投资翻译所需的译文往往是会议文献、年终报表、信贷审批等重要企业金融资料&#xff0c;其准确性事关整个企业在今后一段时期内的发展战略与经营成效。尤其像年报&#xff0c;对于上市公司来说更是至关重要的。那么&#xff0c;怎样做好金融投资翻译&…

Linux shell编程学习笔记21:用select in循环语句打造菜单

一、select in循环语句的功能 Linux shell脚本编程提供了select in语句&#xff0c;这是 Shell 独有的一种循环语句&#xff0c;非常适合终端&#xff08;Terminal&#xff09;这样的交互场景&#xff0c;它可以根据用户的设置显示出带编号的菜单&#xff0c;用户通过输入不同…