用于选择特定内容的正则表达式,前提是它未包含在注释中

时间:2018-03-14 09:32:54

标签: sql regex oracle

我正在寻找一个匹配模式src =“*。js”的正则表达式,但这不应该包含在注释中。

考虑以下

<!------<script type="text/javascript" src="js/Shop.js"></script>  -->
<!----<script type="text/javascript" src="js/Shop.js"></script>  -->
<script type="text/javascript" src="jquery.serialize-object.js"></script>
<script type="text/javascript" src="jquery.cookie.js"></script>

扩展样本输入,由OP描述为“正确”:

<!------<script type="text/javascript" src="js/Shop.js"></script>  -->
<!----<script type="text/javascript" src="js/Shop.js"></script>  -->
<script type="text/javascript" src="jquery.serialize-object.js"></script><!---->
<script type="text/javascript" src="jquery.serialize-object.js"></script><!-- a comment -- afterwards -->
<script type="text/javascript" src="jquery.serialize-object.js"></script><!-- a comment starting but not ending
-- afterwards -->
<script type="text/javascript" src="jquery.serialize-object.js"></script>
<script type="text/javascript" src="jquery.cookie.js"></script>

结果不应与第1行和第2行匹配(其中内容随注释附上)。它应该只匹配第3行和第4行(3端,除了注释结束行,用于扩展的样本输入)。

到目前为止,我有这个正则表达式,它选择我所有的.js文件,还有那些被注释掉的文件:(src=\")+(\S)+(.js)

我正在寻找一个正则表达式,它只选择带有.js src属性但没有注释包围的脚本标记。

我还想提一下,我在Oracle PL SQL查询中使用这个正则表达式。

6 个答案:

答案 0 :(得分:3)

例如此示例输入:

<!------<script type="text/javascript" src="js/Shop.js"></script>  -->
<!----<script type="text/javascript" src="js/Shop.js"></script>  -->
<script type="text/javascript" src="jquery.serialize-object.js"></script><!---->
<script type="text/javascript" src="jquery.serialize-object.js"></script><!-- a comment -- afterwards -->
<script type="text/javascript" src="jquery.serialize-object.js"></script><!-- a comment starting but not ending
-- afterwards -->
<script type="text/javascript" src="jquery.serialize-object.js"></script>
<script type="text/javascript" src="jquery.cookie.js"></script>

这个正则表达式:src="[^"]*\.js\"></script>(\s*<!--[^>]*-->)*(\s*<!--[^>]*)?$
会给你这个输出:

<script type="text/javascript" src="jquery.serialize-object.js"></script><!---->
<script type="text/javascript" src="jquery.serialize-object.js"></script><!-- a comment -- afterwards -->
<script type="text/javascript" src="jquery.serialize-object.js"></script><!-- a comment starting but not ending
<script type="text/javascript" src="jquery.serialize-object.js"></script>
<script type="text/javascript" src="jquery.cookie.js"></script>

我使用GNU grep 2.5.4进行了测试,希望它足够接近你的正则表达式风格。正则表达式对特殊功能非常轻松。

说明:

  • \"[^"]*是&#34; "&#34;
  • 内的任何内容
  • (<!--[^>]*-->)*是&#34;任意数量的完整评论,如果它们不包含>&#34;
  • (<!--[^>]*)?$是&#34;在行尾的非>评论的可选开头&#34;
  • \s*允许可选的空格

请注意,在相关输入可能复杂的某些方面,正则表达式不再是正确的工具。除此之外,还有一个专用工具,即XML / html的解析器。无论如何 对我来说,当相关输入发生隐藏的可能性时,就达到了这一点。在多行注释中。我觉得你把问题变成了一个移动的目标,首先确认允许在一行上预期相关输入(除了后面的评论),然后通过添加矛盾的样本输入来改变规则。有一次你确实描述了我提出的样本输入&#34;正确&#34;。
在评论中讨论QA的(非常有趣的)XML /正则表达式表明,如果你不能尽早绘制线,你最终会陷入困境。
当限制在给定的环境中时,例如SQL服务器,应该利用该环境的特殊功能。当然,通过SQL机制处理输入的非注释部分,以实现一些进一步的目标是可能的。即放下你对如何进行的直接想法,并在思考上稍微绕道而行。尽量确保你不会因XY问题而疲惫不堪。

答案 1 :(得分:3)

我不知道你是否可以用一个正则表达式做你想做的事情,特别是因为Oracle的正则表达式的实现不支持环视。但是您可以使用SQL来解决这些限制。以下将提取模式的匹配项,首先删除文本中的注释,然后匹配剩余的模式src=".*\.js"。使用CONNECT BY检索多个结果:

SELECT html_id, REGEXP_SUBSTR(clean_html, 'src=".*\.js"', 1, LEVEL, 'i') AS match
  FROM (
    SELECT html_id, REGEXP_REPLACE(html_text, '<!--.*?-->', '', 1, 0, 'n') AS clean_html
      FROM (
        SELECT 1 AS html_id, '<!------<script type="text/javascript" src="js/Shop.js"></script>  -->
        <!----<script type="text/javascript" src="js/Shop.js"></script>  -->
        <script type="text/javascript" src="jquery.serialize-object.js"></script><!---->
        <script type="text/javascript" src="jquery.serialize-object.js"></script><!-- a comment -- afterwards -->
        <script type="text/javascript" src="jquery.serialize-object.js"></script><!-- a comment starting but not ending
        -- afterwards -->
        <script type="text/javascript" src="jquery.serialize-object.js"></script>
        <script type="text/javascript" src="jquery.cookie.js"></script>' AS html_text
          FROM dual
    )
)
CONNECT BY REGEXP_SUBSTR(clean_html, 'src=".*\.js"', 1, LEVEL, 'i') IS NOT NULL
   AND PRIOR html_id = html_id
   AND PRIOR DBMS_RANDOM.VALUE IS NOT NULL;

如果这些结果存储在某个表的某个表中,那么您将执行以下操作:

SELECT html_id, REGEXP_SUBSTR(clean_html, 'src=".*\.js"', 1, LEVEL, 'i') AS match
  FROM (
    SELECT html_id, REGEXP_REPLACE(html_text, '<!--.*?-->', '', 1, 0, 'n') AS clean_html
      FROM mytable
)
CONNECT BY REGEXP_SUBSTR(clean_html, 'src=".*\.js"', 1, LEVEL, 'i') IS NOT NULL
   AND PRIOR html_id = html_id
   AND PRIOR DBMS_RANDOM.VALUE IS NOT NULL;

看起来很奇怪,但最后两行是必要的,以避免重复的结果。

结果如下:

| HTML_ID | MATCH                              |
+---------+------------------------------------+
|       1 | src="jquery.serialize-object.js"   |
|       1 | src="jquery.serialize-object.js"   |
|       1 | src="jquery.serialize-object.js"   |
|       1 | src="jquery.serialize-object.js"   |
|       1 | src="jquery.cookie.js"             |
+---------+------------------------------------+

SQL Fiddle HERE.

希望这有帮助。

编辑:根据我的评论编辑:

SELECT html_id, REGEXP_SUBSTR(clean_html, 'src="[^"]*\.js"', 1, LEVEL, 'i') AS match
  FROM (
    SELECT html_id, REGEXP_REPLACE(html_text, '<!--.*?-->', '', 1, 0, 'n') AS clean_html
      FROM (
        SELECT 1 AS html_id, '<!------<script type="text/javascript" src="js/Shop.js"></script>  -->
        <!----<script type="text/javascript" src="js/Shop.js"></script>  -->
        <script type="text/javascript" src="jquery.serialize-object.js"></script><!---->
        <script type="text/javascript" src="jquery.serialize-object.js"></script><!-- a comment -- afterwards -->
        <script type="text/javascript" src="jquery.serialize-object.js"></script><!-- a comment starting but not ending
        -- afterwards -->
        <script type="text/javascript" src="jquery.serialize-object.js"></script>
        <script type="text/javascript" src="jquery.cookie.js"></script>' AS html_text
          FROM dual
    )
)
CONNECT BY REGEXP_SUBSTR(clean_html, 'src="[^"]*\.js"', 1, LEVEL, 'i') IS NOT NULL
   AND PRIOR html_id = html_id
   AND PRIOR DBMS_RANDOM.VALUE IS NOT NULL;

<强> EDITED

如果您正在搜索CLOB而不是CHAR列,则CONNECT BY子句的第一行应如下所示。如果相关列是REGEXP_SUBSTR()CLOB将返回CLOB,并且在这种情况下,比较只需要永远:

CONNECT BY DBMS_LOB.SUBSTR(REGEXP_SUBSTR(clean_html, 'src="[^"]*\.js"', 1, LEVEL, 'i'), 4000, 1) IS NOT NULL

希望这有帮助。

答案 2 :(得分:2)

我在你的正则表达式结束之前做了一个否定的预测,但是请注意,如果在src之后有一个评论的部分,它同样会被忽略。

(src=\")+(\S)+(\.js\")+(?!.*-->)(.*)

修改

我管理了类似的东西而没有前瞻(PL / SQL没有):

(src=\")(\S)+(\.js\")[^(--)\n]+(\n|$)

答案 3 :(得分:0)

这是我的解决方案:一个简单的负面看法。

(?<!<!--.+)src=".+\.js"

这匹配扩展示例中的所有src属性,但不匹配<!--前面的那些属性。这可能就够了,告诉我,如果我错过了一些特定的案例;)

以下是我在扩展示例上运行的解决方案:https://regex101.com/r/rmHkbm/1

编辑:这是在javascript中工作,我不知道ORACLE PL / SQL。有没有办法在不安装Oracle数据库的情况下测试它?

答案 4 :(得分:0)

我不认为可以使用单个正则表达式执行您想要的操作,而不会出现负面情况。但是,您可以通过以一种在SQL中易于执行的方式逻辑组合两个类似的正则表达式来实现。基本思路是:

[MATCH_EXPR] AND NOT [COMMENTED_MATCH_EXPR]

假设我们有一个表data,其中包含line列(代码行),我们可以通过以下方式选择感兴趣的行:

SELECT line
FROM data
WHERE REGEXP_LIKE(line, 'src="[^"]+.js"') AND NOT REGEX_LIKE(line, '<!--.*src="[^"]+.js"');

您可以更新正则表达式以更精确和/或使用它们执行更复杂的操作,例如:捕获文件名,但方法是一样的。

这种方法不是防弹的,因为它无法找到由两个<script>语句组成的行,其中只有第二个被注释掉,因为第二个正则表达式会匹配。然而,它可能适用于绝大多数典型代码,包括上面给出的例子。

答案 5 :(得分:0)

我在https://livesql.oracle.com尝试过以下内容,所以可能适合你。假设未注释的行以'<script'开头。它匹配像

这样的行
    <script type="text/javascript" src="jquery.cookie.js"></script>
    <script type="text/javascript" src="jquery.serialize-object.js"/>
    <script type="text/javascript" src="jquery.serialize-object.js"></script><!-- a comment -- afterwards -->

使用正则表达式查询:

select "SRC" from "TABLE_1" 
where REGEXP_LIKE (SRC, '^\<script.+\.js.+script\>$') 
   or REGEXP_LIKE (SRC, '^\<script.+\.js.+script\>\<\!\-\-.+\-\-\>$') 
   or REGEXP_LIKE (SRC, '^\<script.+\.js.+\/\>$');