首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Regex -序列字符数

Regex -序列字符数
EN

Stack Overflow用户
提问于 2019-04-10 21:40:51
回答 2查看 260关注 0票数 0

我有以下模式:

代码语言:javascript
复制
<tag-2>B1</tag-2>
<tag-3>A12</tag-3>
<tag-4>M123</tag-4>
//etc

总是有一个字母和数字。我需要创建一个regex,它使用标记中的数字,并将其应用于标记之间的序列。我知道我可以使用反向引用,但我不知道如何构造正则表达式。这里是不完全正则表达式:

代码语言:javascript
复制
"^<tag-([2-9])>[A-Z][0-9]/*how to apply here number from the tag ?*/</tag-\\1>$"

编辑

以下字符串不匹配:

代码语言:javascript
复制
<tag-2>11</tag-2> //missing letter
<tag-2>BB</tag-2> // missing digit
<tag-3>B123</tag-3> //too many digits
<tag-3>AA1</tag-3> //should be only one letter and two digits
<tag-4>N12</tag-4> //too few digits
EN

回答 2

Stack Overflow用户

发布于 2019-04-11 05:19:07

正则表达式不能包含作为反向引用值的函数的元素(除了反向引用本身)。这是因为正则表达式在构造时是静态的。

但是,我们可以分两个步骤提取所需的字符串,或者得出结论,sting不包含有效的子字符串。第一次尝试将字符串与/<tag-(\d+)>匹配,其中捕获组的内容在转换为整数后等于以大写字母开头并后面跟着数字的字符串的长度。然后,该信息可用于构造第二个正则表达式,用于验证匹配的其余部分并提取所需的字符串。

我将在这里使用Ruby来说明如何做到这一点。这些操作--当然还有这两个正则表达式--甚至对于不熟悉Ruby的读者来说也应该是明确的。

代码语言:javascript
复制
R = /<tag-(\d+)>/           # a constant

def doit(str)
  m = str.match(R)          # obtain a MatchData object; else nil
  return nil if m.nil?      # finished if no match
  n = m[1].to_i-1           # required number of digits
  r = /\A\p{Lu}\d{#{n}}(?=<\/tag-#{m[1]}>)/
                            # regular expression for second match
  str[m.end(0).to_i..-1][r] # extract the desired string; else nil
end

示例

代码语言:javascript
复制
arr = <<_.each_line.map(&:chomp)
<tag-2>B1</tag-2>
<tag-3>A12</tag-3>
<tag-4>M123</tag-4>
<tag-2>11</tag-2>
<tag-2>BB</tag-2>
<tag-3>B123</tag-3>
<tag-3>AA1</tag-3>
<tag-4>N12</tag-4>
_
  #=> ["<tag-2>B1</tag-2>",   "<tag-3>A12</tag-3>",
  #    "<tag-4>M123</tag-4>", "<tag-2>11</tag-2>",
  #    "<tag-2>BB</tag-2>",   "<tag-3>B123</tag-3>",
  #    "<tag-3>AA1</tag-3>",  "<tag-4>N12</tag-4>"] 

代码语言:javascript
复制
arr.map do |line|
  s = doit(line)
  s = 'nil' if s.nil?
  puts "#{line.ljust(22)}: #{s}"
end
<tag-2>B1</tag-2>     : B1
<tag-3>A12</tag-3>    : A12
<tag-4>M123</tag-4>   : M123
<tag-2>11</tag-2>     : nil
<tag-2>BB</tag-2>     : nil
<tag-3>B123</tag-3>   : nil
<tag-3>AA1</tag-3>    : nil
<tag-4>N12</tag-4>    : nil    

解释

请注意,(?=<\/tag-#{m[1]}>) (方法主体中r的一部分)是一个正的前瞻性,这意味着必须匹配"<\/tag-#{m[1]}>" (替换为#{m[1]} ),但不是返回的匹配的一部分。

一步一步计算如下。

代码语言:javascript
复制
str = "<tag-2>B1</tag-2>"

m = str.match(R)
  #=> #<MatchData "<tag-2>" 1:"2"> 
m[0]
  #=> "<tag-2>"  (match)
m[1]
  #=> "2"  (contents of capture group 1)
m.end(0)
  #=> 7  (index of str where the match ends, plus 1) 
m.nil?
  #=> false  (do not return)
n = m[1].to_i-1
  #=> 1  (number of digits required)
r = /\A\p{Lu}\d{#{n}}(?=\<\/tag\-#{m[1]}\>)/
  #=> /\A\p{Lu}\d{1}(?=\<\/tag\-2\>)/
s = str[m.end(0).to_i..-1]
  #=> str[7..-1]
  #=> "B1</tag-2>" 
s[r]
  #=> "B1" 
票数 1
EN

Stack Overflow用户

发布于 2019-04-10 21:57:23

看起来,您正在尝试创建一个模式来解释一个数字,以确定字符串的长度。我不知道在任何正则表达式引擎中自动化这个过程的任何特性,但是可以通过枚举希望处理的所有情况来以更手动的方式来完成。

例如,可以这样处理标记2到9:

  • <tag-2>^<tag-2>[A-Z][0-9]</tag-2>$
  • <tag-3>^<tag-3>[A-Z][0-9]{2}</tag-3>$
  • <tag-4>^<tag-4>[A-Z][0-9]{3}</tag-4>$
  • <tag-5>^<tag-5>[A-Z][0-9]{4}</tag-5>$
  • <tag-6>^<tag-6>[A-Z][0-9]{5}</tag-6>$
  • <tag-7>^<tag-7>[A-Z][0-9]{6}</tag-7>$
  • <tag-8>^<tag-8>[A-Z][0-9]{7}</tag-8>$
  • <tag-9>^<tag-9>[A-Z][0-9]{8}</tag-9>$

通过删除分组和反向引用,您可以消除在尝试组合正则表达式模式时可能出现的一些复杂情况,并会产生以下结果:

^(<tag-2>[A-Z][0-9]</tag-2>|<tag-3>[A-Z][0-9]{2}</tag-3>|<tag-4>[A-Z][0-9]{3}</tag-4>|<tag-5>[A-Z][0-9]{4}</tag-5>|<tag-6>[A-Z][0-9]{5}</tag-6>|<tag-7>[A-Z][0-9]{6}</tag-7>|<tag-8>[A-Z][0-9]{7}</tag-8>|<tag-9>[A-Z][0-9]{8}</tag-9>)$

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55621692

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档