子串匹配正则表达式中的匹配?

时间:2013-07-10 07:51:08

标签: regex r

我有一个字符串,我需要在其上进行正则表达式匹配(我在R中工作)。它看起来像:

"354542676655341568:1373344735:270969722:text1,text2,text4,text8"

此字符串由colens(:)分隔的4个部分。我有多个具有不同值的字符串,但由相同的4个部分组成。 我计划使用"[0-9]{18}"匹配的第一个数字部分 对于第二部分(它是一个时间戳),我有一段代码生成一个我将追加的范围的正则表达式。示例如下所示:

":0*13733([0-3][0-9]{4}|4([0-3][0-9]{3}|4([0-7][0-9]{2}|800))):"

以上模式匹配1373300000&之间的所有数字。 1373344800。 第三部分也是简单的[0-9]{9}

问题是第四部分,我必须匹配文本部分。我会列出一些文字内容,例如text1text3text5。如果它至少包含列表中的一个文本,我需要接受该字符串。它更像是第四部分的子串匹配。

我曾考虑拆分文本,但在我的应用程序中,这将是一个资源成本高的糟糕设计。因此,我想生成一个完整匹配的正则表达式。

我尝试了一些方法来测试它,但我得到了误报。有任何帮助吗?

checktext = "check:text1,text2,text3"
> grepl("check:[a-zA-Z0-9 ]+,text2",checktext)
[1] TRUE
> grepl("check:[a-zA-Z0-9, ]+,text2",checktext)
[1] TRUE
> grepl("check:[a-zA-Z0-9, ]+,[text3|text2]",checktext)
[1] TRUE
> grepl("check:[a-zA-Z0-9, ]+,[text3|text4]",checktext)
[1] TRUE
> grepl("check:[a-zA-Z0-9, ]+,[text5|text4]",checktext)
[1] TRUE
> grepl("check:[a-zA-Z0-9, ]+,[text5|text4][a-zA-Z0-9, ]$",checktext)
[1] FALSE
> grepl("check:[a-zA-Z0-9, ]+,[text5|text3][a-zA-Z0-9, ]$",checktext)
[1] FALSE
> grepl("check:[a-zA-Z0-9, ]+,[text5|text3][a-zA-Z0-9, ]+?$",checktext)
[1] TRUE
> grepl("check:[a-zA-Z0-9, ]+,[text5|text4][a-zA-Z0-9, ]+?$",checktext)
[1] TRUE
> grepl("check:.*[text1].*",checktext)
[1] TRUE
> grepl("check:.*[text2].*",checktext)
[1] TRUE
> grepl("check:.*[text3].*",checktext)
[1] TRUE
> grepl("check:.*[text2|text4].*",checktext)
[1] TRUE
> grepl("check:.*[text5|text4].*",checktext)

在@sgibb的回复之后,我将所有部分组合在一起,形成最终模式:

"[0-9]{18}:0*13733([0-3][0-9]{4}|4([0-3][0-9]{3}|4([0-7][0-9]{2}|800))):[0-9]{9}:[a-zA-Z0-9, ]+,(Samsung|Nokia)"

我的文字字符串是:

"354542676655341568:1373344735:270969722:Samsung,Galaxy"

它不匹配。是因为把它们全部放在一起了吗?当我从正则表达式中删除最后一个(文本)部分时,它匹配。

> finalpattern
[1] "[0-9]{18}:0*13733([0-3][0-9]{4}|4([0-3][0-9]{3}|4([0-7][0-9]{2}|800))):[0-9]{9}:"

> keysample
    [1] "354542676655341568:1373344735:270969722:Samsung,Galaxy"
    > grepl(finalpattern,keysample)
    [1] TRUE

1 个答案:

答案 0 :(得分:3)

恕我直言,你使用[错误。 [包含要匹配的字符类(意味着 [中的至少一个字符应该匹配)。如果要对模式/字符串进行分组(例如text5|text4),则必须使用(

grepl("check:[a-zA-Z0-9, ]+,(text3|text4)",checktext)
# [1] TRUE
grepl("check:[a-zA-Z0-9, ]+,(text5|text4)",checktext)
# [1] FALSE

这应该可以消除大多数误报。

解决您的修改:

您的正则表达式错误(:之后的部分)。

[a-zA-Z0-9, ]+,:您要查找至少出现的字母数字字符(BTW,请参阅?regex:类[:alnum:]),然后是,。这将再次匹配Samsung

接下来,您要查找(Samsung|Nokia),但只剩下Galaxy

有多种解决方案:

"[[:alnum:], ]*(Samsung|Nokia)[[:alnum:], ]*"

"(Samsung|Nokia),[[:alnum:], ]+"

".*(Samsung|Nokia).*"

# ...

或者您应该考虑将字符串拆分为:并分别对每个部分进行分析。