6

我尝试将字符串拆分为标记。

标记分隔符不是单个字符,一些分隔符包含在其他分隔符中(例如 & 和 &&),我需要将分隔符作为标记返回。
StringTokenizer 无法处理多个字符分隔符。我认为使用 String.split 是可能的,但无法猜测出适合我需要的神奇正则表达式。

任何的想法 ?

例子:

Token delimiters: "&", "&&", "=", "=>", " "  
String to tokenize: a & b&&c=>d  
Expected result: an string array containing "a", " ", "&", " ", "b", "&&", "c", "=>", "d"

--- 编辑 ---
感谢大家的帮助,Dasblinkenlight 为我提供了解决方案。这是我在他的帮助下编写的“即用型”代码:

private static String[] wonderfulTokenizer(String string, String[] delimiters) {
  // First, create a regular expression that matches the union of the delimiters
  // Be aware that, in case of delimiters containing others (example && and &),
  // the longer may be before the shorter (&& should be before &) or the regexpr
  // parser will recognize && as two &.
  Arrays.sort(delimiters, new Comparator<String>() {
    @Override
    public int compare(String o1, String o2) {
      return -o1.compareTo(o2);
     }
  });
  // Build a string that will contain the regular expression
  StringBuilder regexpr = new StringBuilder();
  regexpr.append('(');
  for (String delim : delimiters) { // For each delimiter
    if (regexpr.length() != 1) regexpr.append('|'); // Add union separator if needed
    for (int i = 0; i < delim.length(); i++) {
      // Add an escape character if the character is a regexp reserved char
      regexpr.append('\\');
      regexpr.append(delim.charAt(i));
    }
  }
  regexpr.append(')'); // Close the union
  Pattern p = Pattern.compile(regexpr.toString());

  // Now, search for the tokens
  List<String> res = new ArrayList<String>();
  Matcher m = p.matcher(string);
  int pos = 0;
  while (m.find()) { // While there's a delimiter in the string
    if (pos != m.start()) {
      // If there's something between the current and the previous delimiter
      // Add it to the tokens list
      res.add(string.substring(pos, m.start()));
    }
    res.add(m.group()); // add the delimiter
    pos = m.end(); // Remember end of delimiter
  }
  if (pos != string.length()) {
    // If it remains some characters in the string after last delimiter
    // Add this to the token list
    res.add(string.substring(pos));
  }
  // Return the result
  return res.toArray(new String[res.size()]);
}

如果您有许多字符串要通过仅创建一次 Pattern 来标记化,则可以进行优化。

4

3 回答 3

4

您可以使用Pattern和 一个简单的循环来实现您正在寻找的结果:

List<String> res = new ArrayList<String>();
Pattern p = Pattern.compile("([&]{1,2}|=>?| +)");
String s = "s=a&=>b";
Matcher m = p.matcher(s);
int pos = 0;
while (m.find()) {
    if (pos != m.start()) {
        res.add(s.substring(pos, m.start()));
    }
    res.add(m.group());
    pos = m.end();
}
if (pos != s.length()) {
    res.add(s.substring(pos));
}
for (String t : res) {
    System.out.println("'"+t+"'");
}

会产生以下结果:

's'
'='
'a'
'&'
'=>'
'b'
于 2012-08-31T12:43:47.873 回答
2

拆分不会为您执行此操作,因为它删除了分隔符。您可能需要自己标记字符串(即 for 循环)或使用类似 http://www.antlr.org/的框架

于 2012-08-31T12:59:15.473 回答
1

试试这个:

String test = "a & b&&c=>d=A";
String regEx = "(&[&]?|=[>]?)";

String[] res = test.split(regEx);
for(String s : res){
    System.out.println("Token: "+s);
}

我在末尾添加了“=A”以表明它也被解析了。

正如另一个答案中提到的,如果您需要将分隔符保留在结果中的非典型行为,您可能需要自己创建解析器....但在这种情况下,您真的必须考虑什么是“分隔符”你的代码。

于 2012-08-31T12:55:13.873 回答