我有以下模式:
<tag-2>B1</tag-2>
<tag-3>A12</tag-3>
<tag-4>M123</tag-4>
//etc
总是有一个字母和数字。 我需要创建一个正则表达式,该正则表达式使用标签中的数字并将其应用于标签之间的序列。我知道我可以使用反向引用,但不知道如何构造正则表达式。这是不完整的正则表达式:
"^<tag-([2-9])>[A-Z][0-9]/*how to apply here number from the tag ?*/</tag-\\1>$"
修改
以下字符串不匹配:
<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
答案 0 :(得分:1)
正则表达式不能包含作为反向引用值的函数的元素(反向引用本身除外)。这是因为正则表达式从构建之日起就是静态的。
但是,可以分两个步骤来提取所需的字符串,或者得出结论:该字符串不包含有效的子字符串。第一次尝试将字符串与/<tag-(\d+)>
进行匹配,其中捕获组的内容在转换为整数之后等于以大写字母开头且后跟数字的字符串的长度。然后,该信息可以用于构造第二个正则表达式,用于验证匹配项的其余部分并提取所需的字符串。
我将使用Ruby来说明如何在此处完成。即使对于不熟悉Ruby的读者来说,这些操作以及两个正则表达式也应该很清楚。
代码
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
示例
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>"]
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]}>"
(带有{{1} }替换掉)必须匹配,但不属于返回的匹配的一部分。
分步计算如下。
#{m[1]}
答案 1 :(得分:0)
您似乎正在尝试创建一种模式,该模式将解释数字以便确定字符串应多长。我不知道有任何功能可以在任何正则表达式引擎中自动执行此过程,但是可以通过枚举您希望处理的所有情况以更手动的方式完成。
例如,标签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>)$