如何返回多个正则表达式匹配,结果取决于前一个匹配?

时间:2017-01-05 16:45:27

标签: regex xslt-2.0

我一直在尝试匹配自由文本字段中保存的危险代码。我有一个正则表达式,其中代码以Hxxx格式输入,其中xxx是一个三位数字。简单!

但是,有时用户输入的第一个为Hxxx,后续值为xxx

因此,对于像

这样的输入数据
R12 34 456 / H123 H456 789 012

我希望匹配H123 H456789以及012,而不是第一个456之前的H

编辑:为了澄清,该领域的数据没有明确的模式。大多数情况下,有一些H代码,有时在它们之前有R代码,有时在上面的例子中有界,有时则没有。因此,我设想的规则是,将返回一个以H开头的三位数代码,但任何前面至少有一个H代码的代码都将被忽略。

我已经尝试了我能想到的可选分组和后视的所有组合,而且我得到的最好的是

((H|(?<=(H\d{3}\s)))\d{3}[A-Z]{0,2})

匹配除最后一组之外的所有组,但如果组之间有多个空格,则会导致问题。

我怀疑在xsl:analyze-string命令中,后视可能无法正常工作。

是否有任何巧妙的正则表达式技巧可以用于此,或者我是否需要采用更强力的方法?

1 个答案:

答案 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>,以便提取您要查找的项目。