我一直在尝试匹配自由文本字段中保存的危险代码。我有一个正则表达式,其中代码以Hxxx
格式输入,其中xxx是一个三位数字。简单!
但是,有时用户输入的第一个为Hxxx
,后续值为xxx
。
因此,对于像
这样的输入数据R12 34 456 / H123 H456 789 012
我希望匹配H123
H456
和789
以及012
,而不是第一个456
之前的H
。
编辑:为了澄清,该领域的数据没有明确的模式。大多数情况下,有一些H代码,有时在它们之前有R代码,有时在上面的例子中有界,有时则没有。因此,我设想的规则是,将返回一个以H
开头的三位数代码,但任何前面至少有一个H代码的代码都将被忽略。
我已经尝试了我能想到的可选分组和后视的所有组合,而且我得到的最好的是
((H|(?<=(H\d{3}\s)))\d{3}[A-Z]{0,2})
匹配除最后一组之外的所有组,但如果组之间有多个空格,则会导致问题。
我怀疑在xsl:analyze-string
命令中,后视可能无法正常工作。
是否有任何巧妙的正则表达式技巧可以用于此,或者我是否需要采用更强力的方法?
答案 0 :(得分:0)
您可以使用Saxon 9.6或更高版本的PE和EE(例如在oXygen或Stylus Studio中)或Altova XMLSpy 2017或Exselt和XSLT 3.0吗?在这种情况下,您可以简单tokenize($data, '\s+')
并使用xsl:for-each-group group-starting-with=".[matches(., 'H[0-9]{3}')]
。以下样式表
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:math="http://www.w3.org/2005/xpath-functions/math" exclude-result-prefixes="xs math"
version="3.0">
<xsl:template match="data">
<xsl:copy>
<xsl:variable name="matches" as="xs:string*">
<xsl:for-each-group select="tokenize(., '\s+')"
group-starting-with=".[matches(., 'H[0-9]{3}')]">
<xsl:if test="matches(., 'H[0-9]{3}')">
<xsl:sequence select="current-group()"/>
</xsl:if>
</xsl:for-each-group>
</xsl:variable>
<xsl:value-of select="$matches"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
将<data>R12 34 456 / H123 H456 789 012</data>
转换为<data>H123 H456 789 012</data>
,以便提取您要查找的项目。