0

I'm surprised I didn't find a duplicate of this question. I'm trying to parse out some sql strings and replace the first "SELECT... FROM " string with a different string. I would think it wouldn't be too difficult but haven't hit on the solution yet. If my test string is:

' SELECT something, something_else FROM (SELECT somebody FROM some_table)'

and I want to replace it with:

' SELECT count(*) as total FROM (SELECT somebody FROM some_table)'

I've tried the following regex expressions using REReplaceNoCase():

<cfset SQL = #REReplaceNoCase(test, "^\s*(SELECT.*\s+FROM\s)??", "SELECT count(*) as total FROM ")# />

<cfset SQL = #REReplaceNoCase(test, "^\s*SELECT.*(\s+FROM\s)??", "SELECT count(*) as total FROM ")# />
<cfset SQL = #REReplaceNoCase(test, "^\s*SELECT.*\s+(FROM)??\s", "SELECT count(*) as total FROM ")# />

as well as some other variations. Suggestions?

4

1 回答 1

3

我不会在这里使用替换 - 更容易(也更有效)只需找到第一个 FROM 并将字符串分成两部分,然后将新字符串放在前面:

<cfsavecontent variable="Sql">
    SELECT something, something_else 
    FROM (SELECT somebody FROM some_table)
</cfsavecontent>

<cfset Sql = Sql.split( '(?=\bFROM\b)' , 2 ) />

<cfset Sql = 'SELECT count(*) as total ' & Sql[2] />

<cfdump var=#Sql# />

正则表达式使用前瞻,因此它匹配 FROM 之前的位置,您无需重新添加它。

如有必要,您当然可以更改用于拆分的正则表达式。

例如,使其不区分大小写并使用空格而不是单词边界:

.split( '(?i)(?=\sFROM\s)' , 2 )

第二个参数 (2) 告诉 split 在它有两个字符串后停止(因此第二个数组项包含字符串的其余部分,即使其中可能有更多 FROM)。

另请注意,这是 Java 拆分方法,并将 java.util.regex 用于正则表达式(与 CF 的 Apache ORO 正则表达式有一些差异/改进)。

于 2012-11-07T18:54:13.607 回答