Regexp:排除单词但包括非标准标点符号

时间:2015-09-16 15:06:06

标签: javascript regex string

我想找到包含特定顺序单词的字符串,允许单词之间使用非标准字符,但不包括特定的单词或符号。

我使用javascript的替换函数来查找所有实例并放入数组。

所以,我希望React-Native,除了'之外的所有内容。在两个词之间。或者我可以将select...fromselect...from分开,只要我排除嵌套即可。我认为答案对两者都是一样的,即如何写:在同一个正则表达式中找到x而不是y

从互联网上,我觉得这应该有效:select...from (但是没有找到匹配项。

这可以找到所有/\bselect\b^(?!from).*\bfrom\b/giselect...from但修改它以排除括号"("最后会阻止任何匹配:/\bselect\b[0-9a-zA-Z@\(\)\[\]\s\.\*,%_+-]*?\bfrom\b/gi

有人能告诉我如何排除此正则表达式中的单词和符号吗?

非常感谢 艾玛

编辑:部分字符串输入:

/\bselect\b[0-9a-zA-Z@\(\)\[\]\s\.\*,%_+-]*?\bfrom\b\s*^\(/gi

使用Javascript:

left outer join [stage].[db].[table14] o on p.Project_id = o.project_id

left outer join
(
select
     different_id
    ,sum(costs) - ( sum(brushes) + sum(carpets) + sum(fabric) + sum(other) + sum(chairs)+ sum(apples) ) as overallNumber
    from 
    (
    select ace from [stage].db.[table18] J 

Console.log(选择)应该打印一个数字数组,其中每个数字都是sequel = stringInputAsAbove; var tst = sequel.replace(/\bselect\b[\s\S]*?\bfrom\b/gi, function(a,b) { console.log('match: '+a); selects.push(b); return a; }); console.log(selects); 的起始字符。这适用于我在我的信息中提供的第二个正则表达式,打印:[95,251]。您的\ s \ S变体也是如此,@ sszizhev。

第一个示例select...from也应该这样做但返回[]。

第三个示例^(?!from).*应仅返回251但返回[]。但是我刚刚注意到正面表达式\s*^\(确实给出了95,所以有些进步!这是我出错的消极因素。

1 个答案:

答案 0 :(得分:1)

您的\bselect\b^(?!from).*\bfrom\b正则表达式无法按预期工作,因为:

  1. ^表示行的开头,而不是对下一部分的否定,所以 \bselect\b^表示select字后跟a的开头 线。删除^正则表达式后开始匹配的东西 (DEMO)但它仍然无效。
  2. 多行文本.*中没有修改的
  3. 与新行不匹配, 所以正则表达式只会在单行中匹配select...from,但如果你 更改(.|\n)*(作为一个简单示例)它将match multiline,但仍然无效
  4. *是量化的,所以它会尽可能匹配, 但如果你使用不情愿的量词*?,正则表达式将首先匹配 from字的出现,而int将开始返回relativly correct result
  5. \bselect\b(?!from)表示匹配单独的select字词 紧接着是单独的from字,所以它会是 selectfrom以某种方式由单独的单词组成(因为 select\bfrom)所以(?!from)无效,redundant
  6. 实际上你会得到正则表达式与Stribizhev给你的非常相似:\bselect\b(.|\n)*?\bfrom\b

    在第三个表达式中你犯了同样的错误:\bselect\b[0-9a-zA-Z@\(\)\[\]\s\.\*,%_+-]*?\bfrom\b\s*^\(使用^作为(我假设)否定,而不是一行的开头。移除^,您将再次获得相对有效result(从selectfrom匹配到结束时的)}。

    您的第二个正则表达式与\bselect\b(.|\n)*?\bfrom\b\bselect\b[\s\S]*?\bfrom\b类似。

    我写了#34;相对有效的结果",我也认为,用正则表达式解析SQL可能非常复杂,所以我不确定它是否适用于所有情况。

    您还可以尝试使用正向前瞻来匹配文本中的位置,例如:

    (?=\bselect\b(?:.|\n)*?\bfrom\b)
    

    DEMO - ()已添加到正则表达式,只是为了返回组中匹配的开始索引,因此检查其有效性会更容易

    正则表达式中的否定

    我们在字符类中使用^作为否定,例如[^a-z]表示匹配任何内容但不匹配字母,因此它将匹配数字,符号,空格等,但不匹配范围{{1 } aLook here)。但这种否定是单一性的。我使用z它会阻止正则表达式匹配字符[^from]frodemo)。此外,m将避免匹配[^from]{4},还会fromformetc

    要通过正则表达式来匹配整个单词,您需要使用负面预测,例如morf,这将fail to match,如果将选择单词(?!from),则会放弃给定位置。为避免匹配包含from的整行,您可以使用fromdemo)。

    但是在您的情况下,您不需要使用此构造,因为如果您将贪婪量化^(?!.*from.*).+$替换为.*\bfrom,它将与该单词的首次出现相匹配。更重要的是会遇到问题。看看this regex,它不会匹配任何内容,因为.*?\bfrom不受任何限制,所以只有在(?![\s\S]*from[\s\S]*)之后没有from时它才会匹配,但我们想要匹配select!实际上,这个正则表达式试图立即匹配和排除from,并失败。所以from构造更好地排除匹配的行与给定的单词。

    那么,如果我们不匹配匹配片段中的单词,该怎么办?我认为(?!.*word.*)good solution。使用select\b([^f]|f(?!rom))*?\bfrom\b,它会匹配([^f]|f(?!rom))*?select之间的所有内容,但不会排除from

    但是,如果您只想匹配from而不是select...from,那么最好使用(之类的。但是在你的正则表达式(多行,使用(?!\()(.|\n)*?时,它会导致match到下一个[\s\S]*?部分,因为不情愿的量化将会改变它需要的地方匹配使整个正则表达式。在我看来,好的解决方案是再次使用:

    select...from

    不会与其他select\b([^f]|f(?!rom))*?\bfrom\b(?!\s*?\() 重叠,如果在select..from之后\( - check it here

    ,则不会匹配