替换符号的正则表达式

时间:2011-11-29 15:29:40

标签: java sql regex oracle

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

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

我的第一个想法是使用String#split(String regex)。但是我不知道如何制作一个正则表达式,它只能用那些不在varchars里面的分号来分割。你能建议一个或者可能有另一种方法来解决这个问题吗?

3 个答案:

答案 0 :(得分:2)

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

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

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

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

答案 1 :(得分:1)

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;
   }
}

答案 2 :(得分:1)

这是一个天真的解析器,可能是你正在寻找的。我想过使用正则表达式。起初我认为你的语言实际上不是常规的。

我相信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;
}