StringTokenizer - 如何忽略字符串中的空格

rag*_*jan 1 java string

我试图在单词列表上使用stringtokenizer,如下所示

String sentence=""Name":"jon" "location":"3333 abc street" "country":"usa"" etc
Run Code Online (Sandbox Code Playgroud)

当我使用stringtokenizer并将空格作为分隔符,如下所示

StringTokenizer tokens=new StringTokenizer(sentence," ")
Run Code Online (Sandbox Code Playgroud)

我期待我的输出作为不同的令牌,如下所示

Name:jon

location:3333 abc street

country:usa
Run Code Online (Sandbox Code Playgroud)

但字符串标记器也试图对位置的值进行标记,看起来就像

Name:jon

location:3333

abc

street

country:usa
Run Code Online (Sandbox Code Playgroud)

请让我知道我如何解决上述问题,如果我需要做一个正则表达式,我应该指定什么样的表达式?

anu*_*ava 5

使用CSV阅读器可以轻松处理.

String str = "\"Name\":\"jon\" \"location\":\"3333 abc street\" \"country\":\"usa\"";

// prepare String for CSV parsing
CsvReader reader = CsvReader.parse(str.replaceAll("\" *: *\"", ":"));
reader.setDelimiter(' '); // use space a delimiter
reader.readRecord(); // read CSV record
for (int i=0; i<reader.getColumnCount(); i++) // loop thru columns
    System.out.printf("Scol[%d]: [%s]%n", i, reader.get(i));
Run Code Online (Sandbox Code Playgroud)

更新:这里是纯Java SDK解决方案:

Pattern p = Pattern.compile("(.+?)(\\s+(?=(?:(?:[^\"]*\"){2})*[^\"]*$)|$)");
Matcher m = p.matcher(str);
for (int i=0; m.find(); i++)
    System.out.printf("Scol[%d]: [%s]%n", i, m.group(1).replace("\"", ""));
Run Code Online (Sandbox Code Playgroud)

OUTPUT:

Scol[0]: [Name:jon]
Scol[1]: [location:3333 abc street]
Scol[2]: [country:usa]
Run Code Online (Sandbox Code Playgroud)

现场演示:http://ideone.com/WO0NK6

说明:根据OP的评论:

我正在使用这个正则表达式:

(.+?)(\\s+(?=(?:(?:[^\"]*\"){2})*[^\"]*$)|$)
Run Code Online (Sandbox Code Playgroud)

现在把它分解成更小的块.

PS:DQ代表双重报价

(?:[^\"]*\")                    0 or more non-DQ characters followed by one DQ (RE1)
(?:[^\"]*\"){2}                 Exactly a pair of above RE1
(?:(?:[^\"]*\"){2})*            0 or more occurrences of pair of RE1
(?:(?:[^\"]*\"){2})*[^\"]*$     0 or more occurrences of pair of RE1 followed by 0 or more non-DQ characters followed by end of string (RE2)
(?=(?:(?:[^\"]*\"){2})*[^\"]*$) Positive lookahead of above RE2

.+?  Match 1 or more characters (? is for non-greedy matching)
\\s+ Should be followed by one or more spaces
(\\s+(?=RE2)|$) Should be followed by space or end of string
Run Code Online (Sandbox Code Playgroud)

简而言之:它表示匹配1个或更多长度的任何字符后跟"字符串的空格或结尾".空间必须跟随偶数个DQ.因此,双引号外的空格将匹配,并且双引号内部将不匹配(因为那些后面跟着奇数个DQ).