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

R中的Regex用于检测三个单词的组合以及这些单词的变体,r,regex,R,Regex,我在正则表达式方面不是很有经验,所以我正在联系。如果这是一个重复的问题,请告诉我其他的回答 我的字符串包含三个分组的单词。这三个单词可以在每组中以任何顺序出现。 这些词代表零件号及其修订,可能出现“修订”一词的变体(简称:修订)。修订版也可能不存在。 三个单词中的两个属于一起:如果有两个7位数字,则必须有两个修订 业务背景:我们有一个工程变更数据库,一些变更只包含正在变更的零件的零件号。相关修订位于“说明”字段中。通常,说明包含零件号和版本以及其他文本。 我需要根据说明书对零件进行修改 匹配 我

我在正则表达式方面不是很有经验,所以我正在联系。如果这是一个重复的问题,请告诉我其他的回答

我的字符串包含三个分组的单词。这三个单词可以在每组中以任何顺序出现。 这些词代表零件号及其修订,可能出现“修订”一词的变体(简称:修订)。修订版也可能不存在。 三个单词中的两个属于一起:如果有两个7位数字,则必须有两个修订

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

匹配 我需要返回零件号及其相关版本

单词

  • 7位数字,例如1234567
  • “REV”一词的变体:REV,REV,REV,REV。等)长度为3或4个字符(如果为4个字符,则第4个字符始终为点)。这个词是可选的
  • 一个字母后接两位数字:例如A00、B02、C00 7位字(1234567)和修订(AOO)总是成对出现,可能顺序不一。首字母缩略词“REV”及其变体是可选的
简单且最常见的情况

这三个词按任何顺序只出现一次。单词之间可以有空格,也可以有逗号、冒号、其他文本或其组合。“版本”和变体是可选的

更复杂的情况

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

  • 1234567版本A00 7654321 B00版本C00 1357913 1337335版本A00、1337336

  • 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
regex或例如
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 A)(A C)或(A C)(C B A)
  • (A)(C)(A)(C)
  • 等等
不可能的组合:

  • (甲、乙)
  • (B)或(B)A)
  • (A B)(A C)
  • 等等

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

您可以尝试使用一个正则表达式来查找“字母+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]
返回第一列


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

您可以尝试一个正则表达式,查找“字母+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]
返回第一列


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

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

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

(?![A-Z]\d{2}\b)[^\d\s]+
^ +| +$| (?= )
此正则表达式执行以下操作

(?!       : begin a negative lookahead
  [A-Z]   : match an uppercase letter
  \d{2}   : match 2 digits
  \b      : assert a word boundary
)         : end negative lookahead
[^\d\s]+  : match 1+ characters other than digits and whitespace
^[ ]+    : 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
(?<![^ \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
这会将“真实世界匹配”转换为以下字符串

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

(?![A-Z]\d{2}\b)[^\d\s]+
^ +| +$| (?= )
此正则表达式执行以下操作

(?!       : begin a negative lookahead
  [A-Z]   : match an uppercase letter
  \d{2}   : match 2 digits
  \b      : assert a word boundary
)         : end negative lookahead
[^\d\s]+  : match 1+ characters other than digits and whitespace
^[ ]+    : 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
(?<![^ \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
请注意,为了使空格在上面显示,我将一些表示为包含空格的字符类

将上述字符串转换为以下字符串

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
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}))
当然,您可能希望将结果保存到字符串以外的对象,在这种情况下,我希望这里采用的方法可以轻松修改以满足req