正则表达式:从具有多个匹配项的括号中提取数字
Regex: Extracting numbers from parentheses with multiple matches
如何匹配年份以使其对以下示例具有通用性。
a <- '"You Are There" (1953) {The Death of Socrates (399 B.C.) (#1.14)}'
b <- 'Þegar það gerist (1998/I) (TV)'
我尝试了以下,但没有取得最大的成功。
gsub('.+\(([0-9]+.+\)).?$', '\1', a)
我认为它所做的是直到它找到一个 (,然后它会组成一组数字,然后是任何字符,直到它遇到一个 )。如果有几场比赛,我想提取第一组。
对我哪里出错有什么建议吗?我一直在 R 中这样做。
您的模式包含 .+
部分与尽可能多的 1 个或多个字符匹配,并且您的模式最多可以从传入字符串中获取最后 4 位数字块。
您可以使用
^.*?\((\d{4})(?:/[^)]*)?\).*
替换为 </code> 以仅保留 4 位数字。参见 <a href="https://regex101.com/r/hn6OW2/3" rel="nofollow noreferrer">the regex demo</a>。</p>
<p><strong>详情</strong></p>
<ul>
<li><code>^
- 字符串开头
.*?
- 任何 0+ 个字符尽可能少
\(
- 一个 (
(\d{4})
- 第 1 组:四位数
(?:
- 可选非捕获组的开始
/
- 一个/
[^)]*
- )
以外的任何 0+ 个字符
)?
- 小组结束
\)
- 一个 )
(可选,可以省略)
.*
- 字符串的其余部分。
参见 R demo:
a <- c('"You Are There" (1953) {The Death of Socrates (399 B.C.) (#1.14)}', 'Þegar það gerist (1998/I) (TV)', 'Johannes Passion, BWV. 245 (1725 Version) (1996) (V)')
sub("^.*?\((\d{4})(?:/[^)]*)?\).*", "\1", a)
# => [1] "1953" "1998" "1996"
另一种base R方案是匹配(
后的4位:
regmatches(a, regexpr("\(\K\d{4}(?=(?:/[^)]*)?\))", a, perl=TRUE))
# => [1] "1953" "1998" "1996"
\(\K\d{4}
模式匹配 (
,然后由于 \K
匹配重置运算符而将其删除,然后 (?=(?:/[^)]*)?\))
前瞻确保有一个可选的 /
+ )
以外的 0+ 个字符,然后是 )
。请注意,regexpr
仅提取第一个匹配项。
你可以使用
library(stringr)
strings <- c('"You Are There" (1953) {The Death of Socrates (399 B.C.) (#1.14)}', 'Þegar það gerist (1998/I) (TV)')
years <- str_match(strings, "\((\d+(?: B\.C\.)?)")[,2]
years
# [1] "1953" "1998"
这里的表达式是
\( # (
(\d+ # capture 1+ digits
(?: B\.C\.)? # B.C. eventually
)
注意R
中的反斜杠需要转义。
如何匹配年份以使其对以下示例具有通用性。
a <- '"You Are There" (1953) {The Death of Socrates (399 B.C.) (#1.14)}'
b <- 'Þegar það gerist (1998/I) (TV)'
我尝试了以下,但没有取得最大的成功。
gsub('.+\(([0-9]+.+\)).?$', '\1', a)
我认为它所做的是直到它找到一个 (,然后它会组成一组数字,然后是任何字符,直到它遇到一个 )。如果有几场比赛,我想提取第一组。
对我哪里出错有什么建议吗?我一直在 R 中这样做。
您的模式包含 .+
部分与尽可能多的 1 个或多个字符匹配,并且您的模式最多可以从传入字符串中获取最后 4 位数字块。
您可以使用
^.*?\((\d{4})(?:/[^)]*)?\).*
替换为 </code> 以仅保留 4 位数字。参见 <a href="https://regex101.com/r/hn6OW2/3" rel="nofollow noreferrer">the regex demo</a>。</p>
<p><strong>详情</strong></p>
<ul>
<li><code>^
- 字符串开头
.*?
- 任何 0+ 个字符尽可能少\(
- 一个 (
(\d{4})
- 第 1 组:四位数(?:
- 可选非捕获组的开始
/
- 一个/
[^)]*
-)
以外的任何 0+ 个字符
)?
- 小组结束\)
- 一个 )
(可选,可以省略).*
- 字符串的其余部分。参见 R demo:
a <- c('"You Are There" (1953) {The Death of Socrates (399 B.C.) (#1.14)}', 'Þegar það gerist (1998/I) (TV)', 'Johannes Passion, BWV. 245 (1725 Version) (1996) (V)')
sub("^.*?\((\d{4})(?:/[^)]*)?\).*", "\1", a)
# => [1] "1953" "1998" "1996"
另一种base R方案是匹配(
后的4位:
regmatches(a, regexpr("\(\K\d{4}(?=(?:/[^)]*)?\))", a, perl=TRUE))
# => [1] "1953" "1998" "1996"
\(\K\d{4}
模式匹配 (
,然后由于 \K
匹配重置运算符而将其删除,然后 (?=(?:/[^)]*)?\))
前瞻确保有一个可选的 /
+ )
以外的 0+ 个字符,然后是 )
。请注意,regexpr
仅提取第一个匹配项。
你可以使用
library(stringr)
strings <- c('"You Are There" (1953) {The Death of Socrates (399 B.C.) (#1.14)}', 'Þegar það gerist (1998/I) (TV)')
years <- str_match(strings, "\((\d+(?: B\.C\.)?)")[,2]
years
# [1] "1953" "1998"
这里的表达式是
\( # (
(\d+ # capture 1+ digits
(?: B\.C\.)? # B.C. eventually
)
注意R
中的反斜杠需要转义。