我有以下模式:
<tag-2>B1</tag-2>
<tag-3>A12</tag-3>
<tag-4>M123</tag-4>
//etc总是有一个字母和数字。我需要创建一个regex,它使用标记中的数字,并将其应用于标记之间的序列。我知道我可以使用反向引用,但我不知道如何构造正则表达式。这里是不完全正则表达式:
"^<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发布于 2019-04-11 05:19:07
正则表达式不能包含作为反向引用值的函数的元素(除了反向引用本身)。这是因为正则表达式在构造时是静态的。
但是,我们可以分两个步骤提取所需的字符串,或者得出结论,sting不包含有效的子字符串。第一次尝试将字符串与/<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]}>" (替换为#{m[1]} ),但不是返回的匹配的一部分。
一步一步计算如下。
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" 发布于 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>)$
https://stackoverflow.com/questions/55621692
复制相似问题