【问题标题】:matching certain numbers at the end of a string匹配字符串末尾的某些数字
【发布时间】:2012-11-21 22:08:09
【问题描述】:

我有一个字符串向量:

s <- c('abc1',   'abc2',   'abc3',   'abc11',   'abc12', 
       'abcde1', 'abcde2', 'abcde3', 'abcde11', 'abcde12', 
       'nonsense')

我希望正则表达式仅匹配以abc 开头并以31112 结尾的字符串。换句话说,正则表达式必须排除 abc1 而不是 abc11abc2 但不是 abc12,等等。

我认为使用前瞻断言很容易做到这一点,但我还没有找到方法。有吗?


编辑:感谢下面的发帖人指出原始帖子中的严重歧义。

实际上,我有很多字符串。它们都以数字结尾:一些在 0 中,一些在 9 中,一些在中间的数字中。我正在寻找一个正则表达式,它将匹配所有字符串除了那些以字母结尾的字符串,后跟 1 或 2。(正则表达式也应该只匹配那些以 abc 开头的字符串,但是这是一个简单的问题。)

我尝试使用否定的前瞻断言来创建这样的正则表达式。但我没有任何成功。


感谢所有回复和评论的人。受到你们几个人的启发,我最终使用了这个组合:grepl('^abc', s) &amp; !grepl('[[:lower:]][12]$', s)

【问题讨论】:

    标签: regex r


    【解决方案1】:

    比起一个复杂的正则表达式,在这种情况下,我认为使用两个简单的正则表达式会更容易:

    s <- c('abc1',   'abc2',   'abc3',   'abc11',   'abc12', 
           'abcde1', 'abcde2', 'abcde3', 'abcde11', 'abcde12', 
           'nonsense')
    
    s[grepl("^abc", s) & grepl("(3|11|12)$", s)]
    

    【讨论】:

      【解决方案2】:

      这是你想要的吗?

      s[grepl("abc.*(3|11|12)", s)]
      [1] "abc3"    "abc11"   "abc12"   "abcde3"  "abcde11" "abcde12"
      

      并且排除的字符串是:

      s[!grepl("abc.*(3|11|12)", s)]
      [1] "abc1"     "abc2"     "abcde1"   "abcde2"   "nonsense"
      

      编辑: 正如 cmets 所指出的,您的要求存在一些歧义。更全面的正则表达式将测试字符串开头^ 和字符串结尾$,并且可能只允许字母字符[[:alpha:]] 在最后数字之前:

      s[grepl("^abc[[:alpha:]]*.*(3|11|12)$", s)]
      [1] "abc3"    "abc11"   "abc12"   "abcde3"  "abcde11" "abcde12"
      

      您还可以通过传递参数value=TRUE 来让grep 直接返回值,从而节省代码中的一些重复:

      grep("^abc[[:alpha:]]*.*(3|11|12)$", s, value=TRUE)
      [1] "abc3"    "abc11"   "abc12"   "abcde3"  "abcde11" "abcde12"
      

      【讨论】:

      • 我建议稍作修改:grep("^abc.*(3|11|12)$", s, value=TRUE)^ 匹配字符串的开头,$ 字符串的结尾,正如 OP 所要求的那样。
      • 这也可以匹配 abc33 之类的东西。
      • @Aust:从问题来看,确实应该匹配 abc33(“以 abc 开头,以 3 结尾” - 不以 33 结尾没什么)。
      • 也可以使用grep( ..., value=TRUE)grep( ..., value=TRUE, invert=TRUE)
      • @Aust:啊,对于措辞明确的要求 ;-)
      【解决方案3】:

      在这种情况下你也可以使用substring

      z <- nchar(s)
      s[substring(s, 1, 3) == "abc" & substring(s, z) == "3" | 
          substring(s, z-1) %in%  c("12", "11")] 
      

      【讨论】:

        【解决方案4】:

        专门寻找所要求的数字会给出:

        n <-  c(3,11,12)
        
        s[sub('abc[^[:digit:]]*([[:digit:]]+)$',s, replacement='\\1') %in% n]
         [1] "abc3"    "abc11"   "abc12"   "abcde3"  "abcde11" "abcde12"
        

        这不会将 11 与 1 混淆:

         n <-  c(3,1,12)
        
        s[sub('abc[^[:digit:]]*([[:digit:]]+)$',s, replacement='\\1') %in% n]
         [1] "abc1"    "abc3"    "abc12"   "abcde1"  "abcde3"  "abcde12"
        

        对于您的编辑,不以 1 或 2 结尾(并使用两个正则表达式)

        s[grepl('^abc',s) & !(sub('.*[^[:digit:]]([[:digit:]]+)$',s, replacement='\\1') %in% c(1,2))]
        [1] "abc3"    "abc11"   "abc12"   "abcde3"  "abcde11" "abcde12"
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-12-05
          • 1970-01-01
          • 2019-09-13
          • 2016-01-23
          相关资源
          最近更新 更多