正则表达式以保持单个字符的运行计数

时间:2014-10-26 16:05:17

标签: regex r

考虑以下向量x

x <- c("000a000b000c", "abcd00ab", "abcdefg", "000s00r00g00t00") 

使用单个正则表达式,我只想保留x包含三个以上字母的元素。以下是规则:

  1. 字母并不总是连续的(这是主要问题)
  2. x的字符串元素可以是任意数量的字符
  3. 除数字和小写字母外,字符串中没有任何内容
  4. 我想到的简单方法是删除所有不是字母的内容,然后取出字符数,如下所示。

    x[nchar(gsub("[0-9]+", "", x)) > 3]
    # [1] "abcd00ab"        "abcdefg"         "000s00r00g00t00"
    

    我知道像[a-z]{4,}这样的陈述可以找到四个或更多连续的小写字母。但是,如果单个字母分散在字符串上呢?如何保持字母的“运行计数”,以便当它超过3时,它变成不匹配?现在我所能想到的就是多次写[a-z]+,但如果我想匹配五个或更多字母,这会变得很难看。

    这让我在那里,但你可以看到这对于更长的字符串来说这可能是多么丑陋。

    grep("[a-z]+.*[a-z]+.*[a-z]+.*[a-z]+.*", x)
    # [1] 2 3 4
    

    有没有办法用更好的正则表达式做到这一点?

3 个答案:

答案 0 :(得分:5)

您可以使用重复运算符:{n}匹配上一个标记或组n次。为了提高匹配效率,您还应具体说明字母之间可能匹配的内容(在您的情况下只有数字,而不是&#34;任何&#34;字符(点.匹配)):

^(?:[0-9]*[a-z]){4}[0-9a-z]*$

匹配包含至少3个小写字母的所有字符串。

<强>解释

^         # Start of string
(?:       # Start of a (non-capturing) group:
 [0-9]*   # Match any number of digits
 [a-z]    # Match one lowercase ASCII letter
){4}      # Repeat the group exactly four times
[0-9a-z]* # Then match any following digits/letters
$         # until the end of the string

在R:

grep("^(?:[0-9]*[a-z]){4}[0-9a-z]*$", x, perl=TRUE, value=TRUE);

为您提供一个字符向量,其中包含与正则表达式匹配的所有元素。

答案 1 :(得分:5)

\\D与非数字匹配的情况下尝试此操作,.*匹配0个或更多字符的字符串,(...){4}表示匹配4次,即超过3个。

grep("(\\D.*){4}", x, value = TRUE)

如果有4个或更多的非数字,这将匹配。如果需要超过5,只需将4替换为6.如果在regexp中使用数字3很重要,那么请尝试使用此模式(\\D.*){3}\\D

答案 2 :(得分:3)

下面的grep命令会找到包含四个或更多字母的元素

> grep("^(?:[^a-z]*[a-z]){4}", x, perl=T, value=T)
[1] "abcd00ab"        "abcdefg"         "000s00r00g00t00"

OR

> grep("^(?:[^a-z]*[a-z]){3}[^a-z]*[a-z]", x, perl=T, value=T)
[1] "abcd00ab"        "abcdefg"         "000s00r00g00t00"

要查找包含5个或更多字母的元素,

> grep("^(?:[^a-z]*[a-z]){5}", x, perl=T, value=T)
[1] "abcd00ab" "abcdefg" 

<强>解释

^                        the beginning of the string
(?:                      group, but do not capture (4 times):
  [^a-z]*                  any character except: 'a' to 'z' (0 or
                           more times)
  [a-z]                    any character of: 'a' to 'z'
){4}                     end of grouping