有效删除可能不包含特定单词的子字符串 -

时间:2012-09-13 15:16:22

标签: php regex regex-negation performance regex-lookarounds

我尝试将一些使用php的无效html代码映射到我稍后需要的xml结构。这很有效,但总有一部分我无法处理。所以决定是,只需删除该代码,以便xml保持有效。这就是它的样子。

<body>
    <item>abc</item>
    <item>def</item>
    unparsable rest
</body>

所以我们的目标是找到一个解决方案(可能是正则表达式,但我对任何解决方案都持开放态度)来删除“不可解决的休息”。

我尝试将preg_replace与此正则表达式一起使用

/<\/item>(((?!item).)*)\s*<\/body>/iU

它工作得很好,完全匹配我想要的1美元部分,所有的东西都在最后和之间,但由于xmls非常大,计算只是在几毫秒后崩溃。我知道正则表达式在做出负面的前瞻性方面并不是那么好,但我认为它并不那么糟糕。

因此需要一个更有效的解决方案。不幸的是我不能使用strrpos,因为

之后还有更多的标签

2 个答案:

答案 0 :(得分:1)

您的正则表达式模式中有一个tempered greedy token。它的性质很慢,请参阅我链接到的答案中的“性能问题”部分。

因此,您当前的正则表达式,我更喜欢编写时不带Us修饰符作为~</item>(((?!item).)*?)\s*?</body>~ismatches your input string within 231 steps

请注意,\s*\s*?的语义差异不大,因为</body>之前没有其他量化模式。在这种情况下,最好使用贪婪模式\s*

让我们unroll模式并将((?!item).)*?替换为[^i]*(?:i(?!tem)[^i]*)*~</item>([^i]*(?:i(?!tem)[^i]*)*)\s*</body>~is matches your input within 117 steps

对于字符串来说,这仍然是很多。 </item>之后的空白可以与\s*+进行可能匹配,以减少对该字符串部分的回溯访问。 ~</item>\s*+([^i]*(?:i(?!tem)[^i]*)*)\s*</body>~is显示了一个改进,现在it takes 89 steps可以匹配字符串,并且只有unparsable rest属于第1组值。

不幸的是,由于您想从第1组的值中删除尾随空格,因此我们在这里不能进行太多的回溯。

如果要匹配</item></body>之间不包含<item>的所有字符,则该模式将看起来像~</item>\s*+([^<]*(?:<(?!item>)[^<]*)*)\s*</body>~is,请参见regex demo

答案 1 :(得分:0)

检查每行以“ <”开始,以“>”结束:

        org.apache.log4j.BasicConfigurator.configure();

        try {
            String CERT_PASSWORD = "somePass";

            KeyStore identityKeyStore = KeyStore.getInstance("jks");
            FileInputStream identityKeyStoreFile = new FileInputStream(new File(System.getProperty("user.dir") + "/src/main/resources/files-for-testcases/ultimate.jks"));
            identityKeyStore.load(identityKeyStoreFile, CERT_PASSWORD.toCharArray());


            SSLContext sslContext = SSLContexts.custom()
                    // load identity keystore
                    .loadKeyMaterial(identityKeyStore, CERT_PASSWORD.toCharArray(), (aliases, socket) -> "bddsecurity")
                    .build();

            SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext,
                    new String[]{"TLSv1.2", "TLSv1.1"},
                    null,
                    SSLConnectionSocketFactory.getDefaultHostnameVerifier());

            CloseableHttpClient client = HttpClients.custom()
                    .setSSLSocketFactory(sslConnectionSocketFactory)
                    .build();

            // Call a SSL-endpoint
            return callEndPoint (client, url);
        } catch (Exception ex) {
            System.out.println("Boom, we failed: " + ex);
            ex.printStackTrace();
        }
        return 404;
    }

    private static int callEndPoint (CloseableHttpClient aHTTPClient, String aEndPointURL) {

        try {
            HttpGet httpGet = new HttpGet(aEndPointURL);

            LOG.info("**GET** request Url: " + httpGet.getURI());

            HttpResponse response = aHTTPClient.execute(httpGet);

            int responseCode = response.getStatusLine().getStatusCode();
            LOG.info("Response Code: " + responseCode);
            return responseCode;
        } catch (Exception ex) {
            System.out.println("Boom, we failed: " + ex);
            ex.printStackTrace();
        }
        return 404;
    }

演示:https://3v4l.org/Mt5eG