正则表达式:获取所有单个字符,但不是在单引号之间
regex: get all of a single character, but not when between single quotes
我需要一个 Regex 表达式来捕获字符串中的所有冒号,但当冒号在单引号之间时不需要,然后将其替换为符号 (@)。
我的测试字符串是:
select id, :DATA_INI, ':DATA_INI', titulo, date_format(data_criacao,'%d/%m/%Y %H:%i') str_data_criacao
from v$sugestoes
where data_criacao between :DATA_INI AND :DATA_FIM
order by data_criacao
其实我想要的是:
select id, @DATA_INI, ':DATA_FIM', titulo, date_format(data_criacao,'%d/%m/%Y %H:%i') str_data_criacao
from v$sugestoes
where data_criacao between @DATA_INI AND @DATA_FIM
order by data_criacao
我试过这个正则表达式,但出于某种原因它没有捕捉到第一个冒号:
/(?!'.*?):(?!.*?')/g
PS: 有嵌套引号的可能,也抓不到这些字符串
有人知道我在这里缺少什么吗?我实际上使用的是 C#。
这可以做到:
:(?=([^']*'[^']*')*[^']*$)
它只匹配那些后面有偶数个引号的冒号(正面向前看)。这也涵盖了引号在引号字符串中被转义(对于 SQL)的情况,因为引号前面有另一个引号,因此保持引号计数均匀。
如评论中所述,此正则表达式效率很低,因为它会多次扫描字符串的某些部分:每次找到冒号时,都会扫描字符串的其余部分以查看(非转义)的数量) 引号是偶数。
但对于 SQL 字符串,这似乎是您处理的字符串类型,这应该不是问题,它们通常是不是很长的字符串,也没有数百个引号或冒号.
C# 解决方案
根据上述想法,您可以使用以下 C# 代码:
using System;
using System.Text.RegularExpressions;
class Program
{
static void Main()
{
// This is the input string we are replacing parts from.
string input = "select id, :DATA_INI, ':DATA_INI', titulo, date_format(data_criacao,'%d/%m/%Y %H:%i') str_data_criacao\n"
+ "from v$sugestoes\n"
+ "where data_criacao between :DATA_INI AND :DATA_FIM AND ':TEST'\n"
+ " and 'test ''string :DATA_INI '' :DATA_INI '\n"
+ "order by data_criacao";
string output = Regex.Replace(input, ":(?=([^']*'[^']*')*[^']*$)", "@");
Console.WriteLine(output);
}
}
在 ideone.com 上查看 运行。
由于您使用的是 C#,请尝试:
Regex.Replace(input, @"(?<!'):(\w+)", "@")
这将匹配所有不是 直接 前面有 '
(负向后视)的占位符。
我需要一个 Regex 表达式来捕获字符串中的所有冒号,但当冒号在单引号之间时不需要,然后将其替换为符号 (@)。
我的测试字符串是:
select id, :DATA_INI, ':DATA_INI', titulo, date_format(data_criacao,'%d/%m/%Y %H:%i') str_data_criacao
from v$sugestoes
where data_criacao between :DATA_INI AND :DATA_FIM
order by data_criacao
其实我想要的是:
select id, @DATA_INI, ':DATA_FIM', titulo, date_format(data_criacao,'%d/%m/%Y %H:%i') str_data_criacao
from v$sugestoes
where data_criacao between @DATA_INI AND @DATA_FIM
order by data_criacao
我试过这个正则表达式,但出于某种原因它没有捕捉到第一个冒号:
/(?!'.*?):(?!.*?')/g
有人知道我在这里缺少什么吗?我实际上使用的是 C#。
这可以做到:
:(?=([^']*'[^']*')*[^']*$)
它只匹配那些后面有偶数个引号的冒号(正面向前看)。这也涵盖了引号在引号字符串中被转义(对于 SQL)的情况,因为引号前面有另一个引号,因此保持引号计数均匀。
如评论中所述,此正则表达式效率很低,因为它会多次扫描字符串的某些部分:每次找到冒号时,都会扫描字符串的其余部分以查看(非转义)的数量) 引号是偶数。
但对于 SQL 字符串,这似乎是您处理的字符串类型,这应该不是问题,它们通常是不是很长的字符串,也没有数百个引号或冒号.
C# 解决方案
根据上述想法,您可以使用以下 C# 代码:
using System;
using System.Text.RegularExpressions;
class Program
{
static void Main()
{
// This is the input string we are replacing parts from.
string input = "select id, :DATA_INI, ':DATA_INI', titulo, date_format(data_criacao,'%d/%m/%Y %H:%i') str_data_criacao\n"
+ "from v$sugestoes\n"
+ "where data_criacao between :DATA_INI AND :DATA_FIM AND ':TEST'\n"
+ " and 'test ''string :DATA_INI '' :DATA_INI '\n"
+ "order by data_criacao";
string output = Regex.Replace(input, ":(?=([^']*'[^']*')*[^']*$)", "@");
Console.WriteLine(output);
}
}
在 ideone.com 上查看 运行。
由于您使用的是 C#,请尝试:
Regex.Replace(input, @"(?<!'):(\w+)", "@")
这将匹配所有不是 直接 前面有 '
(负向后视)的占位符。