用于捕获两个周期之间的个位数的正则表达式

Regular expression to capture single digit between two periods

提问人:maryisbiking 提问时间:11/10/2023 最后编辑:r2evansmaryisbiking 更新时间:11/10/2023 访问量:77

问:

我有一个名为 DataFrame 的列,其中包含从 1.1.1 到 14.8.112 的字符串。第一个数字从 1 依次增加到 14,第二个数字从 1 增加到 8,第三个数字从 1 增加到 112。我正在尝试编写一个正则表达式来捕获中间数字,它始终是 1 到 8 的个位数,而不是它周围的两个句点。day_survey_prompt

我尝试过许多正则表达式,包括后视和前瞻,除了中间数字之外,它们总是捕获一个或两个句点。例如,当 day_survey_prompt 的值为 14.5.85 时

str_extract(day_survey_prompt, "[^.]*$")

yields 和85

str_extract(day_survey_prompt, "[^.]*[.$]")

收益 率14.

在此示例中,我想要的输出是5

能让我到达那里的正则表达式是什么?

r 正则表达式

评论


答:

2赞 r2evans 11/10/2023 #1

前期:在您的表达式中,表示“不是字面上的点”,当后面跟着一个(“零或更多”)时,它可以匹配点以外的任何内容。同样,是与文字点或文字美元符号匹配的字符组;如果您打算说“一个点或字符串的末尾,那么在这方面会更好。同样,表示“字符串的开头或文字点”。[^.]*[.$]([.]|$)(^|[.])


使用 lookbehind () 和 lookahead () 提取 Perl 正则表达式:(?<=...)(?=...)

ch <- c("14.8.112", "14.5.85")
regmatches(ch, gregexpr("(?<=[.])[0-9]+(?=[.])", ch, perl = TRUE))
# [[1]]
# [1] "8"
# [[2]]
# [1] "5"

gsub-replacement,假设你总是在某个地方的两个句点之间有一个数字,并且不在乎句点之外是什么:

gsub("^[^.]*\\.([0-9]+)\\..*", "\\1", ch)
# [1] "8" "5"

在 上拆分字符串 ,.

strsplit(ch, "[.]")
# [[1]]
# [1] "14"  "8"   "112"
# [[2]]
# [1] "14" "5"  "85"

并提取每个字符串的第二个:

strsplit(ch, "[.]") |>
  sapply(`[[`, 2)
# [1] "8" "5"

如果它总是一个三元组,你可能想要第一个和第三个,我们可以将它们提取到一个框架中

strcapture("([0-9]+)\\.([0-9]+)\\.([0-9]+)", ch,
           proto=list(first=0L, second=0L, third=0L))
#   first second third
# 1    14      8   112
# 2    14      5    85

使用软件包(感谢您的帮助:-):stringr

# @AndyBaxter
stringr::str_extract(ch, "(?<=\\.)\\d(?=\\.)")
# @nightstand
stringr::str_extract(ch, "\\d{1,2}\\.(\\d)\\.\\d{1,3}", group=1)

(请注意,此示例将收集个位数,不高于 ,因此,如果您想要 -digit 数字,请使用 或 。此外,并且正在根据您的样本数据做出假设,如果前面/后面数字的大小未知,您可能更喜欢。9n\\d+\\d{1,}{1,2}{1,3}+


笔记:

  • 由于是一个表示“任何字符”的正则表达式,我们需要转义它。我已经演示了两种方法,使用(反斜杠转义)或(-组中的句点,仅将 解释为文字句点),它们可以互换使用。.\\.[.][.
  • 同样,“数字”可以正则表达式为 或 ,也可以互换[0-9]\\d

裁判:

评论

1赞 Andy Baxter 11/10/2023
这些都非常方便! 也会起作用str_extract(numbers, "(?<=\\.)\\d(?=\\.)")
2赞 nightstand 11/10/2023
不太优雅的正则表达式,但你也可以在groupstr_extract(ch, "\\d{1,2}\\.(\\d)\\.\\d{1,3}", group=1)
0赞 Reilas 11/10/2023 #2

"...我尝试过许多正则表达式,包括后视和前瞻,除了中间数字之外,它们总是捕获一个或两个句点。..."

请尝试以下匹配模式

(?<=\d\.)[1-8](?=\.\d)
  • (?<=\d\.),正回溯,数字和句点
  • [1-8],匹配一位数,1 到 8
  • (?=\.\d),积极的展望,一个时期和一个数字

或者,更准确的方法是使用捕获模式

\b(?:1[0-4]|[1-9])\.([1-8])\.(?:11[0-2]|10\d|[1-9]\d|[1-9])\b
  • \b,从单词边界开始
  • (?:1[0-4]|[1-9]),匹配值 1 到 14
  • \.([1-8])\.,在两个周期内捕获值
  • (?:11[0-2]|10\d|[1-9]\d|[1-9]),匹配值 1 到 112
  • \b,以单词边界结束