在正则表达式中,+
、*
、和?
是三个常用的量词,分别用来指定前面元素的匹配次数:
+
表示匹配前面的元素一次或多次(至少一次,一次以上)。*
表示匹配前面的元素零次或多次(也可以是不出现,0次以上)。?
表示匹配前面的元素零次或一次(即元素是可选的,0次或1次)。
示例:
假设我们有文本字符串"The rain in Spain falls mainly in the plain."
,并且我们想要使用正则表达式来匹配不同的部分:
使用
+
量词:- 模式:
\w+
等效於[a-zA-Z0-9_] #大小寫字母以及下底線 - 说明:匹配一个或多个字母数字字符或下划线。
- 结果:匹配到’The’, ‘rain’, ‘in’, ‘Spain’, ‘falls’, ‘mainly’, ‘in’, ‘the’, ‘plain’。
- 模式:
使用
*
量词:- 模式:
ai*
- 说明:匹配’a’后面跟随零个或多个’i’。
- 结果:匹配到’ai’ 在”rain” 和 “Spain”中,以及’a’在”plain”中。
- 模式:
使用
?
量词:- 模式:
rai?n
- 说明:匹配’r’后面跟着一个可选的’i’,然后是’n’。
- 结果:匹配到”rain”和”ran”(如果”ran”出现在文本中)。
- 模式:
Python示例代码:
import re
text = "The rain in Spain falls mainly in the plain."
# 使用+
matches_plus = re.findall(r'\w+', text)
print("+:", matches_plus)
# 使用*
matches_star = re.findall(r'ai*', text)
print("*:", matches_star)
# 使用?
matches_question = re.findall(r'rai?n', text)
print("?:", matches_question)
輸出結果:
推薦hahow線上學習python: https://igrape.net/30afN
想要以空白切割字串 str.split(),
但是不想要切割到”degrees C”中的空白
因此需要使用正則表示法
.findall()
import re
# 假设的输入字符串
input_string = 'type="thermal" name="fleeting1" reading="100.000" units="degrees C" validity="valid" timestamp="1701343772.782743" devpath="/phys"'
# 使用re.findall提取键值对
matches: list = re.findall(r'(\w+)="([^"]*)"', input_string)
# 将matches列表转换为字典
data_dict = {key: value for key, value in matches}
print(data_dict)
輸出結果:
这段代码首先使用re.findall
方法与正则表达式(\w+)="([^"]*)"
来查找所有的键值对。这个正则表达式的意思是匹配一个或多个字母数字下划线(\w+
表示键),后面跟着等号和被双引号包围的任意字符("([^"]*)"
表示值),并忽略任何不符合这个模式的文本。
找到所有匹配后,它使用列表推导式将匹配结果转换为字典格式,其中每个键值对作为字典的一个条目。
这个方法可以有效地将你的字符串转换成字典,前提是字符串格式保持一致,且所有的值都用双引号包围。如果字符串格式有所不同,可能需要调整正则表达式来适应这些变化。
在正则表达式中,([^"]*)
是一个非常有用的模式,用于匹配任何不是双引号"
的字符序列。这个模式被封装在一对圆括号内,表示它是一个捕获组,可以从匹配的文本中提取出对应的部分。具体来说:
[^"]
:这部分是一个字符类,^
在字符类的开头表示取反,即匹配除了双引号之外的任何字符。*
:紧跟在字符类后面,表示匹配前面的字符(这里是除了双引号之外的任何字符)0次或多次。
当你问到([^"]*)?
时,?
被添加到整个捕获组的后面,这意味着整个捕获组是可选的。在正则表达式中,?
使得前面的元素(可以是单个字符、字符类、捕获组等)变成可选的,即这个元素可以出现0次或1次。因此:
([^"]*)
:可以匹配任意长度(包括零长度)的非双引号字符序列。([^"]*)?
:可以匹配同样的序列,但它也接受完全没有字符的情况。这意味着即使在双引号之间没有任何内容,这个表达式也能匹配成功。
这种模式通常用于解析带有可选值的键值对数据。例如,在解析HTML属性或类似于你提供的字符串格式时,如果某些键可能没有对应的值,使用([^"]*)?
可以确保这种情况下的匹配也能成功进行。
Python的re
(正则表达式)模块中,当你使用re.findall
函数与包含多个捕获组的正则表达式进行匹配时,re.findall
会自动将每个匹配的结果作为一个元组返回。每个捕获组的匹配结果会按照在正则表达式中出现的顺序被放入这个元组中。
在你的例子中,正则表达式r'(\w+)="([^"]*)"'
包含两个捕获组:
- 第一个捕获组
(\w+)
用来匹配键名,即等号前面的单词(由字母、数字或下划线组成)。 - 第二个捕获组
"([^"]*)"
用来匹配双引号内的值,即等号后面的字符串(可以包含任何字符,除了双引号本身)。
因此,当re.findall
使用这个正则表达式在字符串中查找匹配项时,它会为每个匹配的键值对生成一个元组,元组的第一个元素是键名,第二个元素是对应的值。这就是为什么matches
列表中的每个项都是一个元组的原因。
这种行为使得将匹配的结果直接转换成字典变得非常方便,正如你已经看到的,通过简单地遍历matches
列表并将元组解包为键和值,就可以构建一个字典,其中每个键都映射到相应的值。
推薦hahow線上學習python: https://igrape.net/30afN
在正则表达式中,点(.)、星号(*)、加号(+)、问号(?)都是具有特殊意义的元字符。下面是每个字符的功能和如何使用它们:
点(.)
功能:匹配除换行符(\n)之外的任何单个字符。
示例:a.c 可以匹配 “abc”、”arc”、”a3c” 等,其中 . 代表任何单个字符。
星号() 功能:匹配前面的模式零次或多次。 示例:lol 可以匹配 “ll”、”lol”、”lool”、”loool” 等,其中 o* 表示 “o” 可以出现零次或多次。
加号(+)
功能:匹配前面的模式一次或多次。
示例:lo+l 可以匹配 “lol”、”lool”、”loool” 等,但不能匹配 “ll”,因为这里 o+ 表示 “o” 至少出现一次。
问号(?)
功能:使前面的模式变成可选的,即零次或一次。
示例:colo?r 可以匹配 “color” 和 “colour”,其中 o? 表示 “o” 可以出现零次或一次。
使用特殊字符的字面值
如果你需要在正则表达式中使用这些字符的字面值(例如,匹配一个实际的星号 *),你需要通过在它们前面加上反斜杠(\)来转义这些字符。例如:
要匹配字符串 “a.c”(包含实际的点),使用正则表达式 a.c。
要匹配 “3*2=6″(包含实际的星号),使用正则表达式 3*2=6。
这些元字符是构建强大和灵活的正则表达式的基础,允许你进行复杂的模式匹配和文本处理操作。
*、+ 和 ? 是正则表达式中用来指定前面元素出现次数的三个主要量词(quantifiers)。它们各自的含义和用途如下:
星号() 含义:匹配前面的模式零次或多次。 示例:ab 可以匹配 “b”、”ab”、”aab”、”aaab” 等,其中 a* 表示字符 “a” 可以重复零次或更多次。
加号(+)
含义:匹配前面的模式一次或多次。
示例:a+b 可以匹配 “ab”、”aab”、”aaab” 等,但不能匹配 “b”,因为 a+ 表示字符 “a” 至少出现一次。
问号(?)
含义:使前面的模式成为可选的,即匹配零次或一次。
示例:colou?r 可以匹配 “color” 和 “colour”,其中 u? 表示字符 “u” 可以出现零次或一次。
更多量词
除了这三个基本量词,正则表达式还提供了更灵活的方式来指定次数,如使用花括号 {}:
{n}:匹配前面的模式恰好 n 次。
{n,}:匹配前面的模式至少 n 次。
{n,m}:匹配前面的模式至少 n 次,最多 m 次。
示例
a{2} 会匹配 “aa”,但不会匹配 “a”。
a{2,} 会匹配 “aa”、”aaa”、”aaaa” 等。
a{2,4} 会匹配 “aa”、”aaa” 和 “aaaa”,但不会匹配 “a” 或 “aaaaa”。
使用这些量词可以构建更精确的匹配模式,提供了对字符串模式匹配的强大控制。