我需要匹配组中的所有字符,只要它们与某个单词不匹配即可

时间:2013-11-05 05:13:40

标签: php regex preg-replace

我不确定这是一个简单的问题,但到目前为止我一直无法找到答案。我正在尝试编写一个拉开.docx文件并使用<w:tab />标记替换所有<w:ind />标记的正则表达式,因为<w:tab>标记似乎没有正确保留标签他们翻译成HTML。我正在使用PHP,到目前为止,我还没有成功地编写一个正则表达式来执行我需要它正确执行的操作。

问题是,我不能在这里运行一个简单的查找和替换功能。我必须删除<w:tab />代码并在最近的开始和结束<w:ind />代码中注入<w:rPr></w:rPr>代码。

示例XML字符串看起来像这样:

    <w:p w14:paraId="2679030C" w14:textId="4E6FFA99" w:rsidR="00ED4314" w:rsidRPr="00254747" w:rsidRDefault="00ED4314" w:rsidP="00322270">
        <w:pPr>
            <w:pStyle w:val="NoSpacing" />
            <w:spacing w:line="480" w:lineRule="auto" />
            <w:jc w:val="both" />
            <w:rPr>
                <w:rFonts w:ascii="Times New Roman" w:hAnsi="Times New Roman" w:cs="Times New Roman" />
                <w:sz w:val="24" />
                <w:szCs w:val="24" />
            </w:rPr>
        </w:pPr>
        <w:r w:rsidRPr="00254747">
            <w:rPr>
                <w:rFonts w:ascii="Times New Roman" w:hAnsi="Times New Roman" w:cs="Times New Roman" />
                <w:sz w:val="24" />
                <w:szCs w:val="24" />
            </w:rPr>
            <w:tab />
            <w:t>SOME text</w:t>
        </w:r>
        <w:r w:rsidR="0003297C">
            <w:rPr>
                <w:rFonts w:ascii="Times New Roman" w:hAnsi="Times New Roman" w:cs="Times New Roman" />
                <w:sz w:val="24" />
                <w:szCs w:val="24" />
            </w:rPr>
            <w:t>SOME more text</w:t>
        </w:r>
        <w:r w:rsidRPr="00254747">
            <w:rPr>
                <w:rFonts w:ascii="Times New Roman" w:hAnsi="Times New Roman" w:cs="Times New Roman" />
                <w:sz w:val="24" />
                <w:szCs w:val="24" />
            </w:rPr>
            <w:t>EVEN more text</w:t>
        </w:r>
    </w:p>

因此需要删除<w:tab/>的每个实例,然后我需要向后追溯到之前的<w:rPr>标记,并在其中注入<w:ind />标记。

到目前为止我所拥有的是什么:

$content = preg_replace("/<w:rPr>(.*?)<\/w:rPr>(.*?)<w:tab\/>/", "<w:rPr><w:ind w:firstLine=\"720\"/>$1</w:rPr>$2", $content);

这种工作,但问题是我认为搜索过于全球化。即使我指定它不贪婪,它返回给我的结果有更多的内容然后他们应该。任何人都可以建议一种最佳方法来改进它吗?提前谢谢!

1 个答案:

答案 0 :(得分:1)

我认为你将非贪婪与正常表达混淆“知道”在找到更多标签之前停止 - 这是不可能的。如果您意味着禁止</w:rPr><w:tab/>之间的代码,那么这应该大致有效:

/<w:rPr>(.*?)<\/w:rPr>([^<]*?)<w:tab\/>/
                       ^^^^

这称为否定字符类,并匹配 <的所有字符 - 因此在查找之前不会使用任何其他标记<w:tab/>


修改。为了回应您的澄清,在找到<w:rPr>之前允许 <w:tab/>以外的所有标记 ,你需要使用否定前瞻断言,因为正如你所理解的那样,否定的字符类只排除字符,而不是字符串。

/<w:rPr>(.*?)<\/w:rPr>((?:(?!<w:rPr>).)*?)<w:tab\/>/
                       ^^^^^^^^^^^^^^^^

忽略(?:xyz)如果这让人感到困惑 - 这只是一种方法来获取而不是来捕获 - 我需要括号但量词,{{ 1}}。这里重要的部分是*,它被称为负前瞻断言(顺便提一下也是一个非捕获组)-it 匹配如果向前看 >并且找到“xyz” - 所以我们上面做的是:(1)向前看,(2)如果不是 {{1然后(3)匹配一个字符,(?!xyz),以及(4)重复 - 直到找到<w:rPr>