简体   繁体   English

正则表达式:获取所有单个字符,但不是在单引号之间

[英]regex: get all of a single character, but not when between single quotes

I need a Regex expression to catch all colons in a string, but not when the colon is between single quotes, and then replace it with an at sign (@). 我需要一个Regex表达式来捕获字符串中的所有冒号,但是当冒号位于单引号之间时,然后用at符号(@)替换它。

My test string is: 我的测试字符串是:

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

What I actually want is: 我真正想要的是:

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

I've tried this regex expression, but for some reason it doesn't catch the first colon: 我试过这个正则表达式,但由于某种原因它没有捕获第一个冒号:

/(?!'.*?):(?!.*?')/g

在此输入图像描述 PS: there's a possibility of nested quotes and these strings can't be catched as well. PS:有嵌套引号的可能性,这些字符串也不能被捕获。

Anyone knows what I am missing here? 谁知道我在这里失踪了什么? I´m actually using C#. 我实际上在使用C#。

This could do it: 这可以做到:

:(?=([^']*'[^']*')*[^']*$)

RegEx tester RegEx测试仪

It only matches those colons that have an even number of quotes following it (positive look ahead). 它只匹配那些跟随偶数引号的冒号(正面向前看)。 This also covers the case where quotes are escaped (for SQL) inside quoted string, as those are preceded by another quote and so keep the quote count even. 这也包括引号在引用字符串中被转义(对于SQL)的情况,因为它们之前是另一个引号,因此保持引号计数均匀。

As stated in comments, this regex is rather inefficient because it scans some parts of the string multiple times: each time a colon is found, the rest of the string is scanned to see whether the number of (non-escaped) quotes is even. 正如评论中所述,这个正则表达式是相当低效的,因为它多次扫描字符串的某些部分:每次找到冒号时,扫描字符串的其余部分以查看(非转义)引号的数量是否为偶数。

But for SQL strings, which seems to be the types of strings you deal with, this should not be an issue, they are typically strings that are not extremely long, nor have hundreds of quotes or colons. 但是对于SQL字符串,它似乎是你处理的字符串类型,这不应该是一个问题,它们通常是不是很长的字符串,也没有数百个引号或冒号。

C# solution C#解决方案

Working from the above idea, you could use the following C# code: 根据上述想法,您可以使用以下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);
    }
}

See it run on ideone.com . 看它在ideone.com上运行。

Since you are using C#, try: 由于您使用的是C#,请尝试:

Regex.Replace(input, @"(?<!'):(\w+)", "@$1")

This will match all placeholders which are not directly preceeded by a ' (negative look behind). 这将匹配所有占位符,这些占位符不会直接' (负面观察背后)之前。

Working example: https://dotnetfiddle.net/N43ipM 工作示例: https//dotnetfiddle.net/N43ipM

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM