R中的Regex来检测三个单词的组合以及这些单词的变体

  • 本文关键字:单词 组合 三个 Regex 中的 r regex
  • 更新时间 :
  • 英文 :


我对regex没有太多经验,所以我正在联系。如果这是一个重复的问题,请告诉我其他的回答。

我的字符串包含三个分组的单词。这三个单词可以在每组中以任何顺序出现。这些单词表示零件号及其修订,可能伴随着单词"的变化;rev";(缩写:review)。修订版也可能不存在。三个单词中的两个属于一起:如果有两个7位数的数字,就必须有两个修订!

业务背景:我们有一个工程变更数据库,有些变更只包含正在变更的零件的零件号。相关修订在描述字段中。通常,说明包含零件号和修订以及其他文本。我需要根据说明书对各部分进行修改。

匹配我需要返回零件号及其相关修订版。

单词

  • 7位数字,例如1234567
  • 单词"的变体;REV":REV、REV、REV、REV.等),长度为3或4个字符(如果为4个字符,则第4个字符始终为点)。这个词是可选的
  • 一个字母后面跟着两位数字:例如A00、B02、C007位单词(1234567)和修订(AOO)总是成对出现,可能是混合顺序。首字母缩写";REV";并且其变体是可选的

简单且最常见的情况

这三个单词按任何顺序只出现一次。单词之间可以有空格,也可以有逗号、冒号、其他文本或其组合"REV";并且变化是可选的。

更复杂的情况

这3个单词以混合顺序成组出现多次。真实世界组合示例:

  • 1234567修订版A00 7654321 B00修订版C00 1357913 1337335修订版A001337336

  • 1234567修订版A00一些随机文本7654321 B00修订版C00 1357913 1337335修订版A00

  • 1337336版本A00、1337338版本A00和1337339版本A00

  • 1281660 A01、1281661 b001281839 A01

  • A01 1281660 1281661 B00 A01 1281839

  • 修订版A01 1281660,修订版B00 1281661、1281839 A01

但不可能进行分组组合。例如:

  • 1281660 1281661修订版A01修订版B00
  • 修订版A00、修订版B00、1234567、7654321
  • 1234567修订版A00 7654321 B00 C00

是不可能的(如果他们愿意,我想忽略他们)。换句话说:如果有一个7位数的字符串,它后面必须有一个修订。如果有两个相邻的7位字符串,则前后必须有修订。等

我希望这一点足够清楚。乐于使用base正则表达式或例如stringr函数。非常感谢您的帮助。

更新更多说明,使用括号表示组,使用字母A(7位字符串)、B(字符串"REV"和变体)和C(A00)表示单词。现实的组合,注意A和C必须出现在一个组中:

  • (A B C)、(C B A)、(B A C)、或(A C)或(C A)等。B是可选的
  • (A B C)(C B A)或(A C)(B A C)或(C B C)
  • (A)(C A)(A C)
  • 等等

不可能的组合:

  • (A A A B)
  • (BA)或(BA)
  • (A B B)(A C)
  • 等等

A的出现必须在同一组中看到C。一个A不能与多个B或C联系在一起。如果我们完全忽略B,我想这个问题可以简化。

无论采用何种方法,我建议您从两个步骤开始进行一些简单的预处理。

首先删除Rev及其变体和其他无关文本。您可以通过用空字符串替换以下正则表达式的匹配项来实现这一点。

(?![A-Z]d{2}b)[^ds]+

此正则表达式执行以下操作。

(?!       : begin a negative lookahead
[A-Z]   : match an uppercase letter
d{2}   : match 2 digits
b      : assert a word boundary
)         : end negative lookahead
[^ds]+  : match 1+ characters other than digits and whitespace

这将改变你的";真实世界的匹配";到以下字符串。

1234567  A00 7654321 B00  C00 1357913 1337335  A00
1234567  A00    7654321 B00  C00 1357913 1337335  A00
1337336  A00 1337338  A00  1337339  A00
1281660 A01 1281661 B00 1281839 A01
A01 1281660 1281661 B00 A01 1281839
A01 1281660  B00 1281661 1281839 A01

第二步,不是必要的,但简单方便,是删除每行开头和结尾的空格以及单词之间的额外空格。您可以通过用空字符串替换以下正则表达式的匹配项来实现这一点。

^ +| +$| (?= )

此正则表达式执行以下操作。

^[ ]+    : match 1+ spaces at the beginning of a line
|        : or
[ ]+$    : match  1+ spaces at the end of a line
|        : or
[ ]      : match one space
(?= )    : use a positive lookahead to assert the space is followed
by another space

请注意,为了使空格显示在上面,我将一些空格表示为包含空格的字符类。

这将把上面的字符串转换成下面的字符串。

1234567 A00 7654321 B00 C00 1357913 1337335 A00
1234567 A00 7654321 B00 C00 1357913 1337335 A00
1337336 A00 1337338 A00 1337339 A00
1281660 A01 1281661 B00 1281839 A01
A01 1281660 1281661 B00 A01 1281839
A01 1281660 B00 1281661 1281839 A01

现在可以使用以下正则表达式来匹配每个字符串中的每对7位数字和修订号。7位数字将保存到捕获组1,捕获组4将为空(即,将保存一个空字符串),反之亦然。修订号将保存到捕获组2,捕获组3将为空,反之亦然。

(?<![^ n])(?:(?=d{7} )(d{7}) ([A-Z]d{2})|([A-Z]d{2}) (d{7}))

启动发动机!|R码

此正则表达式执行以下操作。

(?<![^ n])     : negative lookbehind asserts that current position cannot
: be preceded by a character other than a space or newline 
(?:             : begin non-capture group
(?=d{7} )    : positive lookahead asserts that current position is
followed by 7 digits
(d{7})       : match 7 digits, save to capture group 1 
[ ]           : match one space           
([A-Z]d{2})  : match an uppercase letter then 2 digits, save to
capture group 2
|               : or
([A-Z]d{2})  : match an uppercase letter then 2 digits, save to
capture group 3
(d{7})       : match 7 digits, save to capture group 4
)               : end non-capture group

通过用字符串"\1\4 \2\3"替换匹配项,生成以下字符串:

1234567 A00 7654321 B00 1357913 C00 1337335 A00
1234567 A00 7654321 B00 1357913 C00 1337335 A00
1337336 A00 1337338 A00 1337339 A00
1281660 A01 1281661 B00 1281839 A01
1281660 A01 1281661 B00 1281839 A01
1281660 A01 1281661 B00 1281839 A01

当然,您可能希望将结果保存到字符串以外的对象中,在这种情况下,我希望这里采用的方法可以很容易地修改以满足要求。

您可以尝试一个正则表达式来查找;字母+2位数字"+"7位数字";或者换了同样的东西。对于提供的例子,这是有效的:

s = "1234567 Rev A00 7654321 B00 Rev C00 1357913 1337335 Rev A00, 1337336
1234567 Rev A00 some random text 7654321 B00 Rev C00 1357913 1337335 Rev A00
1337336 Rev A00, 1337338 Rev. A00, and 1337339 REV A00
1281660 A01, 1281661 B00,1281839 A01
A01 1281660 1281661 B00 A01 1281839
Rev A01 1281660, REV. B00 1281661, 1281839 A01"
library(stringr)
z = str_match_all(s, "([A-Z]\d{2}.+?\d{7}|\d{7}.+?[A-Z]\d{2})")

返回:

> z
[[1]]
[,1]               [,2]              
[1,] "1234567 Rev A00"  "1234567 Rev A00" 
[2,] "7654321 B00"      "7654321 B00"     
[3,] "C00 1357913"      "C00 1357913"     
[4,] "1337335 Rev A00"  "1337335 Rev A00" 
[5,] "1234567 Rev A00"  "1234567 Rev A00" 
[6,] "7654321 B00"      "7654321 B00"     
[7,] "C00 1357913"      "C00 1357913"     
[8,] "1337335 Rev A00"  "1337335 Rev A00" 
[9,] "1337336 Rev A00"  "1337336 Rev A00" 
[10,] "1337338 Rev. A00" "1337338 Rev. A00"
[11,] "1337339 REV A00"  "1337339 REV A00" 
[12,] "1281660 A01"      "1281660 A01"     
[13,] "1281661 B00"      "1281661 B00"     
[14,] "1281839 A01"      "1281839 A01"     
[15,] "A01 1281660"      "A01 1281660"     
[16,] "1281661 B00"      "1281661 B00"     
[17,] "A01 1281839"      "A01 1281839"     
[18,] "A01 1281660"      "A01 1281660"     
[19,] "B00 1281661"      "B00 1281661"     
[20,] "1281839 A01"      "1281839 A01"     

执行z[[1]][,1]以返回第一列。

您可以在Regex101中尝试更多的情况(它在PHP中,但唯一的区别是在R中,您需要双反斜杠\而不是一个)。

最新更新