用于替换符号的正则表达式

Posted

技术标签:

【中文标题】用于替换符号的正则表达式【英文标题】:Regular expression for replacing symbols 【发布时间】:2011-11-29 15:29:39 【问题描述】:

我正在编写一个可以执行不同 SQL 语句的应用程序(用户将这些语句指定为一个字符串值)。我正在使用 ”;”作为语句之间的分隔符(一次用户可以执行许多 DML 语句)。但是在 DML 语句中可以有一个带有“;”的 varchar 值。里面。

insert into A values(1, 'sda;asdad');
insert into A values(2, 'asdsa');

我的第一个想法是使用String#split(String regex)。但我不知道如何制作一个正则表达式,它只会帮助那些不在 varchars 中的分号进行拆分。您能建议一种或另一种方法来解决这个问题吗?

【问题讨论】:

【参考方案1】:

通常你会通过转义来解决这个问题:

insert into A values(1, 'sda\\;asdad');

然后,当您String#split() 时,请确保 ; 前面没有使用 negative lookbehind 的 \。像这样的:

String rawInput = ...;
String[] statements = rawInput.split("(?<!\\\\);");

【讨论】:

这是个好主意,但最好让用户不知道必须转义分号,因此他/她必须像在 Oracle SQL developer 或 PL/ 中一样输入 sql 字符串SQL 开发人员 如果没有字符转义,您将基本上开始编写解析器。检查分号是否出现在字符串文字中是不平凡的。【参考方案2】:

这是一个简单的解析器,可能正是您要找的。我考虑过使用正则表达式。起初我以为你的语言实际上不是正规的。

我相信 DML 是一种上下文无关语言,但实际上,您的目标语言是常规语言,因为您不关心嵌套语句。您所关心的只是检测***字符串。但是,当您考虑到您的 varchars 中可能存在转义引号时,即使这样也很难使用正则表达式。即如果你有多个 'abcd\'efg'在 varchar 中。

这段代码并不漂亮,但它应该可以满足您的需求。

public static void main(String[] ar) 
    String s = "aaa 'bb;bb;bb' aaa;  aaa 'bb;bb\\';bb' aaa";
    System.out.println(splitStatments(s, ';'));


private static List<String> splitStatments(String s, char statementDelimiter) 
    List<String> statements = new ArrayList<String>();
    StringBuffer sb = new StringBuffer();
    boolean outsideString = true;
    char lastChar = 0;
    for (char c : s.toCharArray()) 
        // in the case of the escaped \', we DON'T want to flip the boolean
        if (c == '\'' && lastChar != '\\') 
            outsideString = !outsideString;
        
        if (c == statementDelimiter && outsideString) 
            statements.add(sb.toString());
            sb = new StringBuffer();
         else 
            sb.append(c);
        
        lastChar = c;
    
    if (sb.length() > 0) 
        statements.add(sb.toString());
    
    return statements;

【讨论】:

【参考方案3】:

下面的比String.split更复杂,但它确实有效:

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Regex2 

   static Pattern pattern = Pattern.compile(".*'(.*);(.*)'.*");

   public static void main(String[] args) 
      String target = "'asdf;asdf';";

      String[] split = split(target);
      if (split == null)
         System.out.println("No match");
      else
         for (String word : split(target))
            System.out.println(word);
   

   static String[] split(String target) 
      Matcher matcher = pattern.matcher(target);
      String[] split = null;
      if (matcher.matches()) 
         split = new String[matcher.groupCount()];
         for (int i = 1; i <= matcher.groupCount(); i++)
            split[i - 1] = matcher.group(i);
      
      return split;
   

【讨论】:

以上是关于用于替换符号的正则表达式的主要内容,如果未能解决你的问题,请参考以下文章

正则表达式替换特殊符号(高分)

量词可以用于R中的正则表达式替换吗?

正则表达式

如何在golang中使用正则表达式替换字符串中的表情符号

使用正则表达式 python 查找和替换符号

39.正则表达式