从字符范围中匹配元素n次

4
假设我有一个像这样的字符串:
id = "ce91ffbe-8218-e211-86da-000c29e211a0"
那么我应该写什么正则表达式(regex)来验证这个字符串是否为36个字符长,并且只包含字母、数字和破折号?
在R中如何使用字符范围(例如[0-9A-z-])与量词(例如{36})没有说明。无论量词是多少,下面的代码始终返回TRUE。我确定我错过了一些简单的东西...
id <- "ce91ffbe-8218-e211-86da-000c29e211a0"

grepl("[0-9A-z-]{36}", id)
#> [1] TRUE

grepl("[0-9A-z-]{34}", id)
#> [1] TRUE

只有当我在字符范围内添加0-9数字的检查时,才会出现这种行为。

3
使用 ^[0-9a-zA-Z-]{36}$ 替代原来的表达式,原因是原来的表达式只匹配了字符串的一部分,所以会返回 true。 - 41686d6564 stands w. Palestine
3个回答

3

请尝试以下操作:

grepl("^[0-9a-zA-Z-]{36}$",id)

OR

grepl("^[[:alnum:]-]{36}$",id)

运行后,我们会得到以下输出结果。
grepl("^[0-9a-zA-Z-]{36}$",id)
[1] TRUE

说明:以下内容仅为解释使用。

grepl("        ##using grepl to check if regex mentioned in it gives TRUE or FALSE result.
^              ##^ means shows starting of the line.
[[:alnum:]-]   ##Mentioning character class [[:alnum:]] with a dash(-) in it means match alphabets with digits and dashes in regex.
{36}           ##Look for only 36 occurences of alphabets with dashes.
$",            ##$ means check from starting(^) to till end of the variable's value.
id)            ##Mentioning id value here.

2

您想使用:

^[0-9a-z-]{36}$
  • ^ 表示匹配行首位置。
  • [0-9a-z-] 匹配数字、小写字母和短横线 -
  • {36} 匹配前面的模式 36 次。
  • $ 表示匹配行尾位置。

在此处尝试:https://regex101.com/r/vjfuBi/1


很好!你需要断言开始和结束的具体原因或直觉是什么? - Steven M. Mortimer
啊,我从上面的评论中看到,显然,只要量词小于字符串的长度,它就会返回TRUE,因为字符串的一部分被匹配了。 - Steven M. Mortimer
如果您不使用断言,则表达式将匹配字符串中的部分子字符串。在一个包含37个字符的字符串中,没有断言的模式将匹配前36个字符。由于您需要精确匹配36个字符,因此需要使用断言。请注意,如果您希望还允许大写字母,则可以将A-Z添加到字符集中。 - Paolo

1
如果字符串在目标字符之前或之后还可能有其他字符,请尝试。
id <- "ce91ffbe-8218-e211-86da-000c29e211a0"
grepl("^[^[:alnum:]-]*[[:alnum:]-]{36}[^[:alnum:]-]*$", id)
#[1] TRUE

grepl("^[^[:alnum:]-]*[[:alnum:]-]{34}[^[:alnum:]-]*$", id)
#[1] FALSE

而且这仍然有效。
id2 <- paste0(":+)!#", id)

grepl("^[^[:alnum:]-]*[[:alnum:]-]{36}[^[:alnum:]-]*$", id2)
#[1] TRUE

grepl("^[^[:alnum:]-]*[[:alnum:]-]{34}[^[:alnum:]-]*$", id2)
#[1] FALSE

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接