【问题标题】:regexp - find numbers in a string in any orderregexp - 以任意顺序查找字符串中的数字
【发布时间】:2015-10-01 11:28:22
【问题描述】:

我需要找到一个正则表达式,它可以让我找到包含所有必需数字但只有一次的字符串。

例如:

a <- c("12","13","112","123","113","1123","23","212","223","213","2123","312","323","313","3123","1223","1213","12123","2313","23123","13123")

我想得到:

"123" "213" "312"

模式 123 只出现一次,并且以任意顺序和字符串的任意位置出现

我尝试了很多东西,这似乎离我想要的还很远:

grep('[1:3][1:3][1:3]', a, value=TRUE)
[1] "113"   "313"   "2313"  "13123"

【问题讨论】:

  • 使用 POSIX 正则表达式,您只能指定所有排列。
  • 相关:stackoverflow.com/questions/3101366/…(实际上是重复的,但如果你使用 pcre 正则表达式)
  • 我认为更简单的正则表达式可以完成这项工作:grep('^[123]{3}$', a, value=TRUE) - 它将找到所有包含 123 数字的 3 位数字。
  • grep('^(?!.*(.).*\1)[123]{3}', a, value=TRUE, perl=T)
  • 非常感谢您的快速回复。我真正需要的是找到包含 1 2 和 3 位的所有 3 位数字

标签: regex r


【解决方案1】:

我真正需要的是找到所有包含 1 2 和 3 位的 3 位数字

那么你就可以放心使用了

grep('^[123]{3}$', a, value=TRUE)
##=> [1] "112" "123" "113" "212" "223" "213" "312" "323" "313"

正则表达式匹配:

  • ^ - 字符串开头
  • [123]{3} - 正好 3 个字符,即 123
  • $ - 断言字符串末尾的位置。

另外,如果您只需要唯一值,请使用unique

如果您不需要多次允许同一数字,则需要基于 Perl 的正则表达式:

grep('^(?!.*(.).*\\1)[123]{3}$', a, value=TRUE, perl=T)
## => [1] "123" "213" "312"

注意双重转义的反向引用。 (?!.*(.).*\\1) 否定前瞻将在捕获组 (.) 和强制相同捕获文本出现在字符串中的反向引用的帮助下检查字符串是否没有重复的符号。如果找到相同的字符,将不匹配。见IDEONE demo

(?!.*(.).*\\1)negative look-ahead。它仅断言当前正则表达式引擎位置 after 不存在某些模式,即,如果不匹配,则检查并返回 true,否则返回 false。因此,它不会“消耗”字符,它不会“匹配”前瞻中的模式,正则表达式引擎会停留在输入字符串中的相同位置。在这个正则表达式中,它是字符串的开头 (^)。因此,就在字符串的开头,正则表达式引擎开始寻找.*(除换行符以外的任何字符,0 次或更多次重复),然后将 1 个字符 (.) 捕获到第 1 组中,再次匹配 0 个或更多字符.*,然后尝试将组 1 中的相同文本与 \\1 匹配。因此,如果有 121,则不会有匹配项,因为前瞻将返回 false,因为它会找到两个 1s。

【讨论】:

  • 非常感谢最后一个可以很好地解决我的问题。因为我是正则表达式的新手,所以 (?!.*(.).*\\1) 是什么意思
  • 我添加了一个扩展解释,说明在开始时锚定的负前瞻对输入字符串的作用。请注意,. 可以在前瞻中使用而没有任何风险,因为我们真正匹配(即消耗并保留在匹配值中)是 12 或 @987654346 @.
【解决方案2】:

你也可以用这个

grep('^([123])((?!\\1)\\d)(?!\\2|\\1)\\d', a, value=TRUE, perl=T)

demo

【讨论】:

  • 它匹配311,因为您只检查第 2 位和第 3 位数字是否与第 1 位数字不同。
  • 唯一的问题是难以扩展。对于某些 SO“大师”来说,这是一个严重的缺点(我过去曾因此类建议而被否决)。
  • 谢谢。为您的回答 +1
猜你喜欢
  • 2016-01-23
  • 1970-01-01
  • 2023-04-10
  • 2020-01-26
  • 2015-11-26
  • 1970-01-01
  • 1970-01-01
  • 2014-08-12
  • 1970-01-01
相关资源
最近更新 更多