使用正则表达式提取多个值
Extract multiple values using regex
你能帮我弄清楚这个正则表达式吗?我的输出看起来像这样:
Wed Aug 30 14:47:11.435 EDT
Interface : p16, Value Count : 9
References : 1, Internal : 0x1
Values : 148, 365, 366, 367, 371
120577, 120578, 120631, 120632
我需要从该输出中提取所有数字。可以有比已经存在的值更多或更少的值。
到目前为止我有这个(但它只提取最后一个值):
\s+Values\s+:\s+((\d+)(?:,?)(?:\s+))+
谢谢
编辑:添加了完整的输出。
[0-9]
这是只匹配字符串中数字的正则表达式。它匹配那里的每个数字。
为什么不只匹配 \d+
(每组一个或多个数字)?
正如@dawg 所提到的,您需要在 Tcl 中采用两步法,因为它的正则表达式不允许在同一个组中存储多个捕获,并且它不支持 \G
运算符。
这是最终的解决方案:
set text {Wed Aug 30 14:47:11.435
EDT Interface : p16,
Value Count : 9 References : 1, Internal : 0x1
Values : 148, 365, 366, 367, 371
120577, 120578, 120631, 120632}
set pattern {\sValues\s*:\s*\d+(?:[\s,]*\d+)*}
regexp $pattern $text match
if {[info exists match]} {
set results [regexp -all -inline {\d+} $match]
puts $results
} else {
puts "No match"
}
查看 Tcl demo 打印 148 365 366 367 371 120577 120578 120631 120632
。
详情
第一个匹配运算符提取以Values
开头然后以逗号或space分隔的数字的子串:
\s
- 白色space
Values
- 一个Values
字
\s*:\s*
- 用 0+ 白色包围的冒号spaces
\d+
- 1 个或多个数字
(?:[\s,]*\d+)*
- 0+ 0+ 白色序列space 或逗号后跟 1+ 数字。
第二步是用 regexp -all -inline {\d+} $match
.
提取所有 1+ 数字块
假设您要搜索字符串 "Values :" 之后的所有数字,并且在这些数字之后没有其他任何内容,您可以使用通常的字符串命令来完成。此 returns 包含数字的列表:
set result [split [string map {\n ","} [string range $text [string first "Values :" $text ]+8 end] ] ","]
从里到外读取它,搜索 "Values :" 字符串的索引。然后从该索引加 8 获取字符串,直到字符串结束。然后使用字符串映射将任何换行符替换为逗号。
最后使用 split 将字符串转换为列表,使用逗号作为分隔符。
假设字符串在变量s
中:
% regexp -inline -all {\d+} [regexp -inline {[^:]+$} $s]
148 365 366 367 371 120577 120578 120631 120632
即:选择最后一个冒号和字符串末尾之间的所有文本(严格来说:由字符串末尾锚定的最长字符序列(来自不包括冒号的字符集))。从此文本中,匹配所有数字组。这是一个与 Wiktor 类似的解决方案,但在第一步中使用了稍微不那么复杂的匹配模式。如果没有匹配也没有问题,因为那只会意味着你在第二步得到一个空的数字列表。
你能帮我弄清楚这个正则表达式吗?我的输出看起来像这样:
Wed Aug 30 14:47:11.435 EDT
Interface : p16, Value Count : 9
References : 1, Internal : 0x1
Values : 148, 365, 366, 367, 371
120577, 120578, 120631, 120632
我需要从该输出中提取所有数字。可以有比已经存在的值更多或更少的值。 到目前为止我有这个(但它只提取最后一个值):
\s+Values\s+:\s+((\d+)(?:,?)(?:\s+))+
谢谢
编辑:添加了完整的输出。
[0-9]
这是只匹配字符串中数字的正则表达式。它匹配那里的每个数字。
为什么不只匹配 \d+
(每组一个或多个数字)?
正如@dawg 所提到的,您需要在 Tcl 中采用两步法,因为它的正则表达式不允许在同一个组中存储多个捕获,并且它不支持 \G
运算符。
这是最终的解决方案:
set text {Wed Aug 30 14:47:11.435
EDT Interface : p16,
Value Count : 9 References : 1, Internal : 0x1
Values : 148, 365, 366, 367, 371
120577, 120578, 120631, 120632}
set pattern {\sValues\s*:\s*\d+(?:[\s,]*\d+)*}
regexp $pattern $text match
if {[info exists match]} {
set results [regexp -all -inline {\d+} $match]
puts $results
} else {
puts "No match"
}
查看 Tcl demo 打印 148 365 366 367 371 120577 120578 120631 120632
。
详情
第一个匹配运算符提取以Values
开头然后以逗号或space分隔的数字的子串:
\s
- 白色spaceValues
- 一个Values
字\s*:\s*
- 用 0+ 白色包围的冒号spaces\d+
- 1 个或多个数字(?:[\s,]*\d+)*
- 0+ 0+ 白色序列space 或逗号后跟 1+ 数字。
第二步是用 regexp -all -inline {\d+} $match
.
假设您要搜索字符串 "Values :" 之后的所有数字,并且在这些数字之后没有其他任何内容,您可以使用通常的字符串命令来完成。此 returns 包含数字的列表:
set result [split [string map {\n ","} [string range $text [string first "Values :" $text ]+8 end] ] ","]
从里到外读取它,搜索 "Values :" 字符串的索引。然后从该索引加 8 获取字符串,直到字符串结束。然后使用字符串映射将任何换行符替换为逗号。 最后使用 split 将字符串转换为列表,使用逗号作为分隔符。
假设字符串在变量s
中:
% regexp -inline -all {\d+} [regexp -inline {[^:]+$} $s]
148 365 366 367 371 120577 120578 120631 120632
即:选择最后一个冒号和字符串末尾之间的所有文本(严格来说:由字符串末尾锚定的最长字符序列(来自不包括冒号的字符集))。从此文本中,匹配所有数字组。这是一个与 Wiktor 类似的解决方案,但在第一步中使用了稍微不那么复杂的匹配模式。如果没有匹配也没有问题,因为那只会意味着你在第二步得到一个空的数字列表。