学习笔记:正则表达式
正则表达式是文本处理方面功能最强大的工具之一。正则表达式语言用来构造正则表达式,最终构造出来的字符串就称为正则表达式,正则表达式用来完成搜索和替换操作。
本文参考《正则表达式必知必会(修订版)》《Learning Regular Expressions》Ben Forta
1 正则表达式
1.1 正则表达式的用途
用一些精心构造的语句,或者说一些由文本和特殊指令构成的高度简练的字符,串用来完成搜索和替换操作。
1.2 如何使用正则表达式
用正则表达式进行搜索
用正则表达式进行替换
1.3 什么是正则表达式
简单地说,正则表达式是一些用来匹配和处理文本的字符串。正则表达式是用正则表达式语言创建的,这种语言专门就是为了解决我们前面所描述的种种问题的。与其他程序设计语言一样,正则表达式语言也有必须要学习的特殊语法和指令。
正则表达式语言并不是一种完备的程序设计语言,它甚至算不上是一种能够直接安装并运行的程序或实用工具。更准确地说,正则表达式语言是内置于其他语言或软件产品里的“迷你”语言。
正则表达式语言虽然也被称为一种语言,但它与人们对语言的印象相去甚远。
2 匹配单个字符
2.1 匹配普通文本
正则表达式可以包含普通文本(甚至可以只包含普通文本)。当然,这种正则表达式纯粹就是一 种浪费。
2.2 匹配任意字符
在正则表达式里,特殊字符(或字符集合)用来标示要搜索的东西。.字符(英文句号)可以匹配任意单个字。
.字符可以匹配任意单个字符、字母、数字甚至是.字符本身。
在同一个正则表达式里允许使用多个.字符,它们既可以共同出现(一个接着一个——..将匹配连续的任意两个字符),也可以分别出现在模式的不同位置。
2.3 匹配特殊字符
.字符在正则表达式里有着特殊的含义。如果模式里需要一个.,就要想办法来告诉正则表达式你需要的是.字符本身而不是它在正则表达式里的特殊含义。为此,你必须在.的前面加上一个\(反斜杠)字符来对它进行转义。\是一个元字符(metacharacter,表示“这个字符有特殊含义,代表的不是字符本身”)。因此,.表示匹配任意单个字符,\.表示匹配.字符本身。
在正则表达式里,\字符总是出现在具有特殊含义字符序列的开头,这个序列可以由一个或多个字符构成。
2.4 小结
正则表达式,也被称为模式,其实是一些由字符构成的字符串。这些字符可以是字面字符(普通文本)或元字符(有特殊含义的字符)。在这一章里,介绍了如何使用普通文本和元字符去匹配单个字符。.可以匹配任意单个字符。\用来对字符进行转义。在正则表达式里,有特殊含义的字符序列总是以\字符开头。
3 匹配一组字符
3.1 匹配多个字符中的某一个
在正则表达式里,我们可以使用元字符[和]来定义一个字符集合。在使用[和]定义的字符集合里,出现在[和]之间的所有字符都是该集合的组成部分,必须匹配其中某个成员(但并非全部)。
3.2 利用字符集合区间
在使用正则表达式的时候,会频繁地用到一些字符区间(0~9、A~Z等)。为了简化字符区间的定义,正则表达式提供了一个特殊的元字符:可以用-(连字符)来定义字符区间。
字符区间的首、尾字符可以是ASCII字符表里的任意字符。但在实际工作中,最常用的字符区间还是数字字符区间和字母字符区间。
提示 在定义一个字符区间的时候,一定要避免让这个区间的尾字符小于它的首字符(例如[3-1])。这种区间是没有意义的,而且往往会让整个模式失效。
注意 -(连字符)是一个特殊的元字符,它只有出现在[和]之间的时候才是元字符。在字符集合以外的地方,-只是一个普通字符,只能与-本身相匹配。因此,在正则表达式里,-字符不需要被转义。
在同一个字符集合里可以给出多个字符区间。比如说,下面这个模式可以匹配任何一个字母(无论大小写)或数字,但除此以外的其他字符(既不是数字也不是字母的字符)都不匹配: [A-Za-z0-9]
3.3 排除
不用逐个列出你要匹配的字符(如果只是要把一小部分字符排除在外的话,这种写法就太冗长了),可以使用元字符^来排除某个字符集合。
注意 ^的效果将作用于给定字符集合里的所有字符或字符区间,而不是仅限于紧跟在^字符后面的那一个字符或字符区间。
3.4 小结
元字符[和]用来定义一个字符集合,其含义是必须匹配该集合里的字符之一(各个字符之间是OR 的关系,而不是 AND 的关系)。
定义一个字符集合的具体做法有两种:一是把所有的字符都列举出来;二是利用元字符-以字符区间的方式给出。
可以用元字符^排除字符集合,强制匹配指定字符集合之外的字符。
4 使用元字符
4.1 再谈转义
元字符是一些在正则表达式里有着特殊含义的字符。任何一个元字符都可以通过在前面加上一个反斜杠字符(\)进行转义。
警告 配对的元字符(比如[或])不用作元字符时必须被转义,否则正则表达式解析器很可能会抛出一个错误。
对元字符进行转义需要用到\字符。这意味着\字符也是一个元字符,它的特殊含义是对其他元字符进行转义。在需要匹配\本身的时候,我们必须把它转义为\\。
4.2 匹配空白字符
元字符大致可以分为两种:一种是用来匹配文本的(比如.),另一种是正则表达式语法的组成部分(比如[和])。
空白元字符
| [\b] | 回退(并删除)一个字符(Backspace 键) |
| \f | 换页符 |
| \n | 换行符 |
| \r | 回车符 |
| \t | 制表符(Tab 键) |
| \v | 垂直制表符 |
4.3 匹配特定的字符类型
4.3.1 匹配数字(与非数字)
| \d | 任何一个数字字符(等价于[0-9]) |
| \D | 任何一个非数字字符(等价于[^0-9]) |
提示 正则表达式的写法几乎总是不止一种。挑选你自己觉得最舒服的那种即可。
4.3.2 匹配字母数字(与非字母数字)
| \w | 任何一个字母数字字符(大小写均可)或下划线字符(等价于 [a-zA-Z0-9_]) |
| \W | 任何一个非字母数字或非下划线字符(等价于[^a-zA-Z0-9_]) |
4.3.3 匹配空白字符(与非空白字符)
| \s | 任何一个空白字符(等价于[\f\n\r\t\v]) |
| \S | 任何一个非空白字符(等价于[^\f\n\r\t\v]) |
注意 用来匹配退格字符的[\b]元字符不在\s的覆盖范范围内,\S也没有将其排除。
4.3.4 匹配十六进制或八进制数
| \x | 十六进数 |
| \o | 八进制数 |
注意 有不少正则表达式实现还允许使用\c前缀来指定各种控制字符。比如说,\cZ可以匹配Ctrl-Z。不过,在实践中,极少会用到这种语法。
4.4 使用POSIX字符类
| [:alnum:] | 任何一个字母或数字(等价于[a-zA-Z0-9]) |
| [:alpha:] | 任何一个字母(等价于[a-zA-Z]) |
| [:blank:] | 空格或制表符(等价于[\t]) |
| [:cntrl:] | ASCII 控制字符(ASCII 0 到 31,再加上 ASCII 127) |
| [:digit:] | 任何一个数字(等价于[0-9]) |
| [:graph:] | 和[:print:]一样,但不包括空格 |
| [:lower:] | 任何一个小写字母(等价于[a-z]) |
| :print:] | 任何一个可打印字符 |
| [:punct:] | 既不属于[:alnum:],也不属于[:cntrl:]的任何一个字符 |
| [:space:] | 任何一个空白字符,包括空格(等价于[\f\n\r\t\v ]) |
| [:upper:] | 任何一个大写字母(等价于[A-Z]) |
| [:xdigit:] | 何一个十六进制数字(等价于[a-fA-F0-9] |
注意 JavaScript不支持在正则表达式里使用POSIX字符类。
4.5 小结
这一章介绍了匹配特定字符(制表符、换行符等)或字符集合或字符类(数字、字母数字字符等)的元字符。这些简写的元字符和POSIX字符类可以用来简化正则表达式模式。
5 重复匹配
5.1 有多少个匹配
| + | 匹配一个或多个字符(至少一个;不匹配零个字符的情况)。 |
| * | 匹配零个或多个字符。 |
| ? | 只能匹配某个字符(或字符集合)的零次或一次出现,最多不超过一次。 |
5.2 匹配的重复次数
正则表达式里的+、*和?解决了许多问题,但有时候光靠它们还不够。请思考以下问题。
- +和*匹配的字符个数没有上限。我们无法为其匹配的字符个数设定一个最大值。
- +、*和?匹配的字符最小数量是零个或一个。我们无法明确地为其匹配的字符个数另行设定一个最小值。
- 我们无法指定具体的匹配次数。
5.2.1 具体的重复匹配
要想设置具体的匹配次数,把数字写在{和}之间即可。比如说,{3} 意味着匹配前一个字符(或字符集合)3 次。如果只能匹配 2 次,则不算是匹配成功。
5.2.2 区间范围
{}语法还可以用来为重复匹配次数设定一个区间范围,也就是匹配的最小次数和最大次数。比如说,{2,4},意味着最少重复 2 次,最多重复 4 次。
5.2.3 匹配“至少重复多少次”
重复范围的最后一种用法是指定至少要匹配多少次,比如说,{3,} 表示至少重复 3 次,换句话说,就是“重复 3 次或 更多次”。
注意 +在功能上等价于{1,}。
5.3 防止过度匹配
因为*和+都是所谓的“贪婪型”(greedy)元字符,其匹配行为是多多益善而不是适可而止。它们会尽可能地从一段文本的开头一直匹配到末尾,而不是碰到第一个匹配时就停止。这是有意设计 的,量词就是贪婪的。
在不需要这种“贪婪行为”的时候该怎么办?答案是使用这些量词的“懒惰型”(lazy)版本(之所以称之为“懒惰型”是因为其匹配尽可能少的字符,而非尽可能多地去匹配)。懒惰型量词的写法是在贪婪型量词后面加上一个?。
贪婪型量词和懒惰型量词
| 贪婪型量词 | 懒惰型量词 |
| * | *? |
| + | +? |
| {n,} | {n,}? |
5.4 小结
在使用重复匹配时,正则表达式的真正威力就显现出来了。本章介绍了+(匹配字符或字符集合的一次或多次重复出现)、*(匹配字符或字符集合的零次或多次重复出现)和?(匹配字符或字符集合的零次或一次出现)的用法。要想获得更大的控制权,你可以用重复范围{}来精确地设定重复次数或是重复的最小次数和最大次数。量词分“贪婪型”和“懒惰型”两种,前者会尽可能多地匹配,后者则会尽可能少地匹配
6 位置匹配
位置匹配用于指定应该在文本中什么地方进行匹配操作。
6.1 边界
边界,就是一些用于指定模式前后位置(或边界)的特殊元字符。
6.2 单词边界
第一种边界(也是最常用到的)是由\b指定的单词边界。顾名思义,\b用来匹配一个单词的开头或结尾。
b 是英文 boundary(边界)的首字母。
注意 \b 到底匹配什么东西呢?正则表达式引擎不懂英语(事实上,它不懂任何人类语言),所以也不知道什么是单词边界。简单地说,\b匹配的是字符之间的一个位置:一边是单词(能够被\w匹配的字母数字字符和下划线),另一边是其他内容(能够被\W匹配的字符)。
重要的是要认识到,如果你想匹配一个完整的单词,就必须在要匹配的文本的前后都加上\b。
如果你不想匹配单词边界,那么可以使用\B。\B-\B将匹配一个前后都不是单词边界的连字符。
6.3 字符串边界
单词边界可以用来对单词位置进行匹配(单词的开头、单词的结尾、整个单词等)。字符串边界有着类似的用途,只不过用于在字符串首尾进行模式匹配。字符串边界元字符有两个:^代表字符串开头,$代表字符串结尾。
多行模式
^和$通常分别匹配字符串的首尾位置。但也有例外,或者说有办法改变这种行为。
许多正则表达式都支持使用一些特殊的元字符去改变另外一些元字符的行为,(?m)就是其中之一,它可用于启用多行模式(multiline mode)。多行模式迫使正则表达式引擎将换行符视为字符串分隔符,这样一来,^既可以匹配字符串开头,也可以匹配换行符之后的起始位置(新行);$不仅能匹配字符串结尾,还能匹配换行符之后的结束位置。
在使用时,(?m)必须出现在整个模式的最前面。
6.4 小结
正则表达式不仅可以用来匹配任意长度的文本块,还可以用来匹配出现在字符串中特定位置的文本。\b 用来指定一个单词边界(\B 刚好相反)。^和$用来指定字符串边界(字符串的开头和结尾)。如果与(?m)配合使用,^和$还可以匹配换行符之前或之后的字符串。
7 使用子表达式
本章将学习如何运用子表达式(subexpression)对表达式进行分组。
7.1 理解子表达式
?或*或{2},只是用来表明重复次数的元字符,指定的重复次数只作用于紧挨着它的前一个字符,而不能作用于更长的部分。
7.2 使用子表达式进行分组
子表达式是更长的表达式的一部分。划分子表达式的目的是为了将其视为单一的实体来使用。子表达式必须出现在字符(和)之间。
提示 (和)是元字符。如果需要匹配(和)本身,就必须使用转义序列\(和\)。
7.3 子表达式的嵌套
子表达式允许嵌套,还可以多重嵌套。
7.4 小结
子表达式使用(和)来定义,作用是把表达式的各个部分划分在一起。子表达式的常见用途包括:通过重复次数元字符准确地控制重复内容,正确地定义|的多项分支。如有必要,子表达式还允许嵌套使用。
8 反向引用
子表达式的另一种重要用途——反向引用(backreference)
8.1 理解反向引用
后面匹配的内容需要引用以前匹配一部分。
“反向引用”指的是这些实体引用的是先前的子表达式。
8.2 反向引用匹配
\1 到底是什么意思?它匹配模式中所使用的第一个子表达式,\2 匹配第二个子表达式、\3 匹配第三个,以此类推。
提示 可以把反向引用想象成变量。
警告 反向引用只能用来引用括号里的子表达式。
8.3 替换操作
当用到反向引用时,正则表达式的替换操作才会真正发挥作用。
大小写转换
用来进行大小写转换的元字符
| 元字符 | 说 明 |
| \E | 结束\L 或\U 转换 |
| \l | 把下一个字符转换为小写 |
| \L | 把\L 到\E 之间的字符全部转换为小写 |
| \u | 把下一个字符转换为大写 |
| \U | 把\U 到\E 之间的字符全部转换为大写 |
8.4 小结
子表达式用来定义字符或表达式的集合。除了可以用于重复匹配(详见第 7 章),还可以在模式的内部被引用。这种引用被称为反向引用(遗憾的是,反向引用的语法在不同的正则表达式中存在差异)。在文本匹配和替换操作中,反向引用颇为有用。
9 环视
到目前为止,我们见过的正则表达式都是用来匹配文本的,但有时你可能想用正则表达式标记要匹配的文本位置(而不是文本自身)。这就要用到环视(lookaround,能够前后查看)了,这正是本章要讨论的话题。
注意 所有主流的正则表达式实现都支持前者,但支持后者的就没那么多了。Java、.NET、PHP、Python和Perl都支持向后查看(其中一些有限制),JavaScript则不支持
9.1 环视简介
环视就是想办法构造出一种模式,该模式中包含一些不用被返回的匹配——这些匹配是为了找出正确的匹配位置,其自身不属于最终的匹配结果。换句话说,你需要进行“环视”。
9.2 向前查看
向前查看模式的语法是一个以?=开头的子表达式,需要匹配的文本跟在=的后面。
?=告诉正则表达式引擎:匹配文本只是为了向前查看(不用消耗该部分)。
9.3 向后查看
向后查看操作符是?<=
因为要匹配文本相对于模式的方向(对应“向前查看”的“前”)与文本阅读方向正相反,记忆向后查看<号的方向容易引起误解,所以可以直接将“?<=”读成“向……之后查看”。
警告 向前查看模式的长度是可变的,其中可以包含.和+等量词,所以非常灵活。向后查看模式则只能是固定长度。几乎所有的正则表达式实现都有此限制。
9.4 结合向前查看和向后查看
向前查看和向后查看可以组合在一起使用
9.5 否定式环视
向前查看和向后查看通常都是用来匹配文本,主要用于指定作为匹配结果返回的文本位置(指明所需匹配之前或之后的文本)。这种用法被称为肯定式向前查看(positive lookahead)和肯定式向 后查看(positive lookbehind)。术语“肯定式”(positive)是指要执行的是匹配操作。
环视还有一种不太常见的形式叫作否定式环视(negative lookaround)。否定式向前查看(negative lookahead)会向前查看不匹配指定模式的文本,否定式向后查看(negative lookbehind)则向后查看不匹配指定模式的文本。
各种环视操作
| 种 类 | 说 明 |
| (?=) | 肯定式向前查看 |
| (?!) | 否定式向前查看 |
| (?<=) | 肯定式向后查看 |
| (?<!) | 否定式向后查看 |
提示 一般来说,凡是支持向前查看的正则表达式实现也都支持肯定式向前查看和否定式向前查看。类似地,凡是支持向后查看的正则表达式实现也都支持肯定式向后查看和否定式向后查看。
9.6 小结
环视可以更精细地控制最终的返回结果。
环视操作允许利用子表达式来指定文本匹配操作的发生位置,但同时又不会消耗匹配到的文本 (不出现在最终的匹配结果里)。
肯定式向前查看使用(?=)来定义,否定式向前查看使用(?!)来定义。
有些正则表达式实现还支持肯定式向后查看(相应的操作符是(?<=))和否定式向后查看(相应的操作符是(?<!))。
10 嵌入式条件
正则表达式语言还有一个威力强大但不经常被用到的特性:在表达式的内部嵌入条件处理。
10.1 为什么要嵌入条件
如果不使用条件处理根本无法编写的模式。
警告 并非所有的正则表达式实现都支持条件处理。
10.2 正则表达式里的条件
正则表达式里的条件要用?来定义。事实上,我们已经见过几种非常具体的条件了。
- ?匹配前一个字符或表达式,如果它存在的话。
- ?=和?<=匹配前面或后面的文本,如果它存在的话。
嵌入式条件语法也使用了?,这并没有什么让人感到吃惊的地方,因为嵌入式条件不外乎以下两种情况。
- 根据反向引用来进行条件处理。
- 根据环视来进行条件处理。
10.2.1 反向引用条件
反向引用条件仅在一个前面的子表达式得以匹配的情况下才允许使用另一个表达式。
用来定义这种条件的语法是(?(backreference)true),其中?表明这是一个条件,括号里的 backreference是一个反向引用,仅当反向引用立即出现时,才对表达式求值。
条件还可以有else表达式,仅当给定的反向引用不存在(也就是不符合条件)时才执行该表达式。用来定义这种条件的语法是(?(backreference) true|false)。此语法接受一个条件和两个分别在符合/不符合该条件时执行的表达式。
10.2.2 环视条件
环视条件允许根据向前查看或向后查看操作是否成功来决定要不要执行表达式。环视条件的语法与反向引用条件的语法大同小异,只需把反向引用(括号里的反向引用编号)替换为一个完整的环视表达式就行了。
向前查看和向后查看(肯定式和否定式皆可)都可作为条件,也可使用可选的else表达式(语法和之前看到的一样,即|expression)。
提示 环视条件用的并不是很多,因为使用更简单的方法往往可以实现差不多的结果。
10.3 小结
在正则表达式模式里可以嵌入条件,只有满足条件(或者没有满足)的时候,才执行相应的表达式。条件可以是反向引用(检查其是否存在),也可以是环视操作。
11 常见问题的正则表达式解决方案
| 北美电话号码 | [\(.]?[2-9]\d\d[\).]?[ -]?[2-9]\d\d[-.]\d{4} |
| 中国固定电话号码 | ((?=\()\(0[1-9]\d{1,2}\)|0[1-9]\d{1,2}-)\d{2,4}\s?\d{3,4} |
| 美国ZIP编码 | \d{5}(-\d{4})? |
| 中国邮政编码 | \d(9|[0-7])\d{4} |
| 加拿大邮政编码 | [ABCEGHJKLMNPRSTVXY]\d[A-Z] \d[A-Z]\d |
| 英国邮政编码 | [A-Z]{1,2}\d[A-Z\d]? \d[ABD-HJLNP-UW-Z]{2} |
| 美国社会安全号码SSN | \d{3}-\d{2}-\d{4} |
| 中国公民身份号码 | [1-8]\d{16}[0-9X] |
| IP地址 | (((\d{1,2})|(1\d{2})|(2[0-4]\d)|(25[0-5]))\.){3} ((\d{1,2})|(1\d{2})|(2[0-4]\d)|(25[0-5])) |
| URL | https?:\/\/[-\w.]+(:\d+)?(\/([\w\/_.]*)?)? |
| 完整的URL | https?:\/\/(\w*:\w*@)?[-\w.]+(:\d+)?(\/([\w\/_.]*(\?\S+)?)?)? |
| 电子邮件地址 | (\w+\.)*\w+@(\w+\.)+[A-Za-z]+ |
| HTML注释 | <!-{2,}.*?-{2,}> |
| JavaScript注释 | \/\/.* |
| 信用卡号码 | MasterCard卡 5[1-5]\d{14} |
| Visa 卡 4\d{12}(\d{3})? |
小结
在本章,你看到了我们在前面章节里介绍的许多概念和思路在实际中的应用例子。这些例子里的模式可以随意拿来使用或改动。我们将其作为一份见面礼,欢迎大家进入令人兴奋且富有成效的正则表达式世界。
附录A 常见应用软件和编程语言中的正则表达式
略
相关文章:
学习笔记:正则表达式
正则表达式是文本处理方面功能最强大的工具之一。正则表达式语言用来构造正则表达式,最终构造出来的字符串就称为正则表达式,正则表达式用来完成搜索和替换操作。 本文参考《正则表达式必知必会(修订版)》《Learning Regular Exp…...
03-抓包_封包_协议_APP_小程序_PC应用_WEB应用
抓包_封包_协议_APP_小程序_PC应用_WEB应用 一、参考工具二、演示案例:2.1、WEB应用站点操作数据抓包-浏览器审查查看元素网络监听2.2、APP&小程序&PC抓包HTTP/S数据-Charles&Fiddler&Burpsuite2.3、程序进程&网络接口&其他协议抓包-WireSh…...
C语言笔试题之实现C库函数 strstr()(设置标志位)
实例要求: 1、请你实现C库函数strstr()(stdio.h & string.h),请在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始);2、函数声明:int strStr(char* h…...
什么是IDE,新手用哪个IDE比较好
什么是IDE IDE(Integrated Development Environment,集成开发环境)是一种为程序员提供软件开发所需的代码编辑、构建、调试等功能于一体的应用程序。IDE通常包含了代码编辑器、编译器、调试器和图形用户界面等工具,这些工…...
Flask 入门6:模板继承
1. 一个网站中,大部分网页的模块是重复的,比如顶部的导航栏,底部的备案信息。如果在每个页面中都重复的去写这些代码,会让项目变得臃肿,提高后期的维护成本。比较好的做法是,通过模板继承,把一…...
欢迎来到操作系统的世界
🌞欢迎来到操作系统的世界 🌈博客主页:卿云阁 💌欢迎关注🎉点赞👍收藏⭐️留言📝 🌟本文由卿云阁原创! 🙏作者水平很有限,如果发现错误ÿ…...
寒假作业-day5
1>现有无序序列数组为23,24,12,5,33,5347,请使用以下排序实现编程 函数1:请使用冒泡排序实现升序排序 函数2:请使用简单选择排序实现升序排序 函数3:请使用直接插入排序实现升序排序 函数4:请使用插入排序实现升序排序 代码: #include<stdio.h&g…...
互联网加竞赛 基于深度学的图像修复 图像补全
1 前言 🔥 优质竞赛项目系列,今天要分享的是 基于深度学的图像修复 图像补全 该项目较为新颖,适合作为竞赛课题方向,学长非常推荐! 🧿 更多资料, 项目分享: https://gitee.com/dancheng-se…...
用于制作耳机壳的UV树脂耳机壳UV胶价格高不高?
制作耳机壳的UV树脂价格相对于一些其他材料可能会略高,但具体的价格取决于多个因素,如品牌、型号、质量等。一些高端的UV树脂品牌和型号可能会价格较高,但它们也通常具有更好的性能和更广泛的应用范围。 此外,UV树脂的价格也与购买…...
【开源】JAVA+Vue+SpringBoot实现房屋出售出租系统
目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 房屋销售模块2.2 房屋出租模块2.3 预定意向模块2.4 交易订单模块 三、系统展示四、核心代码4.1 查询房屋求租单4.2 查询卖家的房屋求购单4.3 出租意向预定4.4 出租单支付4.5 查询买家房屋销售交易单 五、免责说明 一、摘…...
Golang 并发 生产者消费者模式
Golang 并发 生产者消费者模式 生产者-消费者模式能够带来的好处 生产者消费者模式是一种常见的并发编程模式,用于解决生产者和消费者之间的数据传递和处理问题。在该模式中,生产者负责生成数据(生产),而消费者负责处…...
Win32 SDK Gui编程系列之--ListView自绘OwnerDraw
ListView自绘OwnerDraw 1.ListView自绘OwnerDraw 正在试错是否使用了列表视图,尽量制作出智能的表格编辑器。本页显示了业主抽签的表格数据(二维数组数据)的显示方法。 显示画面和整个程序如下所示。使用ListView_GetSubItemRect宏的话,就不需要getRect函数了。 当nCol的…...
深度学习本科课程 实验5 循环神经网络
循环神经网络实验 任务内容 理解序列数据处理方法,补全面向对象编程中的缺失代码,并使用torch自带数据工具将数据封装为dataloader分别采用手动方式以及调用接口方式实现RNN、LSTM和GRU,并在至少一种数据集上进行实验从训练时间、预测精度、…...
Redis篇之过期淘汰策略
一、数据的过期策略 1.什么是过期策略 Redis对数据设置数据的有效时间,数据过期以后,就需要将数据从内存中删除掉。可以按照不同的规则进行删除,这种删除规则就被称之为数据的删除策略(数据过期策略)。 2.过期策略-惰…...
【Kubernetes】kubectl top pod 异常?
目录 前言一、表象二、解决方法1、导入镜像包2、编辑yaml文件3、解决问题 三、优化改造1.修改配置文件2.检查api-server服务是否正常3.测试验证 总结 前言 各位老铁大家好,好久不见,卑微涛目前从事kubernetes相关容器工作,感兴趣的小伙伴相互…...
前后端分离项目:前端的文件夹应该叫什么名字,后端呢
在前后端分离的项目中,为了提高项目的可读性和易管理性,给前端和后端的文件夹选择合适的名字是很重要的。这里提供一些建议,但请记住,最终的命名应该根据你的团队习惯、项目特性以及可能的公司规定来决定。 ### 前端文件夹命名建…...
2024.2.6
1.现有无序序列数组为23,24,12,5,33,5347,请使用以下排序实现编程 函数1:请使用冒泡排序实现升序排序 函数2:请使用简单选择排序实现升序排序 函数3:请使用快速排序实现升序排序 函数4:请使用插入排序实现升序排序 #include<stdio.h> #include<string.h&g…...
如何在 Microsoft Azure 上部署和管理 Elastic Stack
作者:来自 Elastic Osman Ishaq Elastic 用户可以从 Azure 门户中查找、部署和管理 Elasticsearch。 此集成提供了简化的入门体验,所有这些都使用你已知的 Azure 门户和工具,因此你可以轻松部署 Elastic,而无需注册外部服务或配置…...
在Visual Studio中引用和链接OpenSceneGraph (OSG) 库
在Visual Studio中引用和链接OpenSceneGraph (OSG) 库,按照以下步骤操作: 构建或安装OSG库 下载OpenSceneGraph源代码(如3.0版本)并解压。使用CMake配置项目,为Visual Studio生成解决方案文件。通常您需要设置CMake中的…...
[缓存] - Redis
0.为什么要使用缓存? 用缓存,主要有两个用途:高性能、高并发。 1. 高性能 尽量使用短key 不要存过大的数据 避免使用keys *:使用SCAN,来代替 在存到Redis之前压缩数据 设置 key 有效期 选择回收策略(maxmemory-policy) 减…...
基于ASP.NET+ SQL Server实现(Web)医院信息管理系统
医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上,开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识,在 vs 2017 平台上,进行 ASP.NET 应用程序和简易网站的开发;初步熟悉开发一…...
苍穹外卖--缓存菜品
1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得,如果用户端访问量比较大,数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据,减少数据库查询操作。 缓存逻辑分析: ①每个分类下的菜品保持一份缓存数据…...
LLM基础1_语言模型如何处理文本
基于GitHub项目:https://github.com/datawhalechina/llms-from-scratch-cn 工具介绍 tiktoken:OpenAI开发的专业"分词器" torch:Facebook开发的强力计算引擎,相当于超级计算器 理解词嵌入:给词语画"…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
Device Mapper 机制
Device Mapper 机制详解 Device Mapper(简称 DM)是 Linux 内核中的一套通用块设备映射框架,为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程,并配以详细的…...
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中,新增了一个本地验证码接口 /code,使用函数式路由(RouterFunction)和 Hutool 的 Circle…...
如何应对敏捷转型中的团队阻力
应对敏捷转型中的团队阻力需要明确沟通敏捷转型目的、提升团队参与感、提供充分的培训与支持、逐步推进敏捷实践、建立清晰的奖励和反馈机制。其中,明确沟通敏捷转型目的尤为关键,团队成员只有清晰理解转型背后的原因和利益,才能降低对变化的…...
Spring Security 认证流程——补充
一、认证流程概述 Spring Security 的认证流程基于 过滤器链(Filter Chain),核心组件包括 UsernamePasswordAuthenticationFilter、AuthenticationManager、UserDetailsService 等。整个流程可分为以下步骤: 用户提交登录请求拦…...
spring Security对RBAC及其ABAC的支持使用
RBAC (基于角色的访问控制) RBAC (Role-Based Access Control) 是 Spring Security 中最常用的权限模型,它将权限分配给角色,再将角色分配给用户。 RBAC 核心实现 1. 数据库设计 users roles permissions ------- ------…...
PydanticAI快速入门示例
参考链接:https://ai.pydantic.dev/#why-use-pydanticai 示例代码 from pydantic_ai import Agent from pydantic_ai.models.openai import OpenAIModel from pydantic_ai.providers.openai import OpenAIProvider# 配置使用阿里云通义千问模型 model OpenAIMode…...
