我想查找包含按特定顺序排列的单词的字符串,允许在单词之间使用非标准字符,但排除特定的单词或符号。
我正在使用javascript的replace函数来查找所有实例并将其放入数组。
因此,我想要select...from
,在单词之间加上“ from”以外的任何内容。或者,只要我不嵌套,就可以将select...from
与select...from (
分开。我认为两者的答案是相同的,即我该怎么写:在同一个正则表达式中找到x而不是y?
从互联网上,我认为这应该可行:/\bselect\b^(?!from).*\bfrom\b/gi
,但没有找到匹配的内容。
这可以找到所有select...from
:/\bselect\b[0-9a-zA-Z@\(\)\[\]\s\.\*,%_+-]*?\bfrom\b/gi
,但是将其修改为排除括号“(”可以防止任何匹配:/\bselect\b[0-9a-zA-Z@\(\)\[\]\s\.\*,%_+-]*?\bfrom\b\s*^\(/gi
谁能告诉我如何在此正则表达式中排除单词和符号?
非常感谢
艾玛
编辑:部分字符串输入:
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
Javascript:
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);
Console.log(selects)应该打印一个数字数组,其中每个数字都是
select...from
的起始字符。这适用于我在信息中输入的第二个正则表达式,打印:[95,251]。您的\ s \ S变体也一样,@ stribizhev。第一个示例
^(?!from).*
应该也这样做,但返回[]。第三个示例
\s*^\(
应该仅返回251,但返回[]。但是我刚刚注意到,正向表达式\s*\(
的确给出了95,所以进步了!这是我误会的负面因素。
最佳答案
您的\bselect\b^(?!from).*\bfrom\b
正则表达式无法正常运行,因为:^
在这里表示一行的开头,而不是下一部分的否定,所以\bselect\b^
的意思是select
单词,后跟一个
线。删除^
正则表达式后,开始匹配某些内容
(DEMO),但仍然无效。
多行文字.*
中未经修改的行将不匹配换行,
因此正则表达式将仅在单行中匹配select...from
,但是如果您
将其更改为(.|\n)*
(作为简单示例),它将变为match
multiline,但仍然无效*
是greetquantfire,因此它将尽可能匹配,
但是,如果您使用勉强的quantifire *?
,则正则表达式将与第一个匹配
出现from
字,并且int将开始返回relativly
correct result。\bselect\b(?!from)
表示匹配单独的select
单词,不是
直接在其后跟一个单独的from
字,这样就可以selectfrom
以某种方式由单独的单词组成(因为select\bfrom
),所以(?!from)
不起作用,它是redundant
实际上,您将获得与Stribizhev给您的正则表达式非常相似的正则表达式:\bselect\b(.|\n)*?\bfrom\b
在第三个表达式中,您会犯同样的错误:\bselect\b[0-9a-zA-Z@\(\)\[\]\s\.\*,%_+-]*?\bfrom\b\s*^\(
使用^
作为(我假设)一个否定,而不是一行的开头。删除^
,您将再次获得相对有效的result(从select
到from
匹配到封闭式)
)。
您的第二个正则表达式的工作方式类似于\bselect\b(.|\n)*?\bfrom\b
或\bselect\b[\s\S]*?\bfrom\b
。
正如我也认为的那样,我写了“相对有效的结果”,其中用正则表达式解析SQL可能非常复杂,因此我不确定它是否在每种情况下都可以使用。
您也可以尝试使用正向前瞻来匹配文本中的位置,例如:
(?=\bselect\b(?:.|\n)*?\bfrom\b)
DEMO-将
()
添加到正则表达式中只是为了返回分组中的匹配开始索引,因此更容易检查其有效性正则表达式中的否定
我们在字符类中使用
^
作为否定符,例如[^a-z]
表示匹配任何内容,但不匹配字母,因此它将匹配数字,符号,空格等,但不匹配范围a
到z
([^from]
它将阻止正则表达式匹配字符f
,r
,o
和m
(Look here)。同样,[^from]{4}
将避免匹配from
,但也将避免匹配form
,morf
,demo。要从正则表达式匹配中排除整个单词,您需要使用负向前看,例如
(?!from)
,如果选择的单词from
处于给定位置,则会使用etc。为了避免匹配包含from
的整行,可以使用^(?!.*from.*).+$
(fail to match)。但是,根据您的情况,您无需使用此构造,因为如果用
.*\bfrom
替换贪婪的quantifire .*?\bfrom
,它将与该词的首次出现相匹配。更何况它会引起问题。看一下demo,它不会匹配任何内容,因为(?![\s\S]*from[\s\S]*)
不受任何限制,因此仅当from
之后没有select
时它才匹配,但我们也想匹配from
!实际上,此正则表达式尝试一次匹配并排除from
并失败。因此(?!.*word.*)
构造可以更好地排除与给定单词匹配的行。那么,如果我们不匹配匹配片段中的单词,该怎么办?我认为
select\b([^f]|f(?!rom))*?\bfrom\b
是this regex。对于([^f]|f(?!rom))*?
,它将匹配select
和from
之间的所有内容,但不会排除from
。但是,如果您只想匹配
select...from
而不是后跟(
,那么最好使用(?!\()
这样。但是在您的正则表达式(多行,使用(.|\n)*?
或[\s\S]*?
的情况下,它会导致good solution扩展到下一个select...from
部分,因为不情愿的quantfire将在需要匹配以形成整个正则表达式的地方形成一个色带)。意见认为,好的解决方案是再次使用:select\b([^f]|f(?!rom))*?\bfrom\b(?!\s*?\()
它不会与其他
select..from
重叠,并且如果\(
-match之后有select...from
,则不会匹配
关于javascript - 正则表达式:排除单词,但包括非标准标点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32612359/