我想查找包含按特定顺序排列的单词的字符串,允许在单词之间使用非标准字符,但不包括特定的单词或符号。
我正在使用javascript的replace函数来查找所有实例并放入数组。
所以,我想要select...from
,在单词之间除了'from'以外的任何东西。或者我可以把select...from
和select...from (
分开,只要我排除嵌套。我认为答案是相同的,即我如何写:找到x而不是y在相同的正则表达式?
从互联网上,我觉得这应该工作:/bselectb^(?!from).*bfromb/gi
,但这没有找到匹配。
这可以找到所有的select...from
: /bselectb[0-9a-zA-Z@()[]s.*,%_+-]*?bfromb/gi
,但修改它以排除末尾的括号"("会阻止任何匹配:/bselectb[0-9a-zA-Z@()[]s.*,%_+-]*?bfrombs*^(/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(/bselectb[sS]*?bfromb/gi, function(a,b) { console.log('match: '+a); selects.push(b); return a; });
console.log(selects);
Console.log(select)应该打印一个数字数组,其中每个数字都是select...from
的起始字符。这适用于我在info中给出的第二个regexp,打印:[95,251]。你的s s变体也一样,@stribizhev。
第一个示例^(?!from).*
应该做同样的事情,但返回[]。
第三个示例s*^(
应该只返回251,但返回[]。然而,我刚刚注意到,积极的表达s*(
确实给95,所以一些进展!
您的bselectb^(?!from).*bfromb
正则表达式不像预期的那样工作,因为:
-
^
这里表示一行的开始,而不是下一部分的否定,所以bselectb^
表示,select
字后跟a的开头线。移除^
后,regex开始匹配某些东西(DEMO)但仍然无效。 - 在多行文本
.*
中未经修改将不匹配新行,所以regex将只匹配select...from
单行,但是如果你将其更改为(.|n)*
(作为一个简单的示例),它将匹配多行,但仍然无效 -
*
是贪婪的量化,所以它会尽可能地匹配,但如果您使用不情愿的量化*?
, regex将首先匹配当from
字出现时,int将开始相对返回正确结果。 -
bselectb(?!from)
表示不匹配单独的select
字直接跟在单独的from
单词后面,所以应该是selectfrom
不知何故由单独的单词组成(因为selectbfrom
)所以(?!from)
不工作,它是多余的
实际上你将得到与Stribizhev给你的非常相似的正则表达式:bselectb(.|n)*?bfromb
在第三个表达式中,您犯了同样的错误:bselectb[0-9a-zA-Z@()[]s.*,%_+-]*?bfrombs*^(
使用^
作为(我假设)否定,而不是行开头。删除^
,您将再次获得相对有效的结果(从select
到from
匹配到关闭旁括号)
)。
第二个正则表达式的工作原理类似于bselectb(.|n)*?bfromb
或bselectb[sS]*?bfromb
。
我写了"相对有效的结果",因为我也认为,用正则表达式解析SQL可能非常复杂,所以我不确定它是否会在每种情况下工作。
您也可以尝试使用正向前看来匹配文本中的位置,例如:
(?=bselectb(?:.|n)*?bfromb)
DEMO - ()
被添加到regex只是为了返回匹配组的开始索引,所以它会更容易检查它的有效性
正则表达式
我们在字符类中使用^
作为否定,例如[^a-z]
表示匹配除字母以外的任何内容,因此它将匹配数字,符号,空格等,但不匹配a
到z
范围内的字母(看这里)。但这种否定是在单个角色的层面上。如果您使用[^from]
,它将阻止regex匹配字符f
, r
, o
和m
(演示)。此外,[^from]{4}
将避免匹配from
,但也会匹配form
, morf
等。
要通过regex排除整个单词的匹配,您需要使用负查找,如(?!from)
,如果在给定位置后面有被选中的单词from
,则将无法匹配。为了避免匹配包含from
的整行,您可以使用^(?!.*from.*).+$
(demo)。
然而,在你的情况下,你不需要使用这种结构,因为如果你用.*?bfrom
替换贪婪量化.*bfrom
,它将匹配这个词的第一次出现。更重要的是,它会带来问题。看看这个正则表达式,它不会匹配任何东西,因为(?![sS]*from[sS]*)
不受任何限制,所以只有在select
之后没有from
时才会匹配,但我们也想匹配from
!实际上,这个正则表达式试图匹配并排除from
,并且失败。因此,(?!.*word.*)
结构可以更好地排除与给定单词匹配的行。
那么,如果我们不匹配匹配片段中的单词该怎么办呢?我认为selectb([^f]|f(?!rom))*?bfromb
是一个很好的解决方案。对于([^f]|f(?!rom))*?
,它将匹配select
和from
之间的所有内容,但不会排除from
。
但是如果你想只匹配select...from
而不匹配(
,那么使用(?!()
是一个好主意。但是在您的regex(多行)中,使用(.|n)*?
或[sS]*?
将导致匹配到下一个select...from
部分,因为不情愿的量化将改变需要匹配的地方以使整个regex。在我看来,好的解决方案是再次使用:
selectb([^f]|f(?!rom))*?bfromb(?!s*?()
不会重叠额外的select..from
,如果select...from
后面有(
,则不会匹配-在这里检查