我正在尝试在单词列表中使用stringtokenizer,如下所示
String sentence=""Name":"jon" "location":"3333 abc street" "country":"usa"" etc
当我使用stringtokenizer并将空格作为分隔符时,如下所示
StringTokenizer tokens=new StringTokenizer(sentence," ")
我期待我的输出为不同的令牌,如下所示
Name:jon
location:3333 abc street
country:usa
但字符串标记器也试图对位置值进行标记,它看起来像
Name:jon
location:3333
abc
street
country:usa
请让我知道如何解决上述问题,如果我需要做正则表达式,我应该指定哪种表达式?
答案 0 :(得分:5)
使用CSV Reader可以轻松处理。
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));
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("\"", ""));
<强>输出:强>
Scol[0]: [Name:jon]
Scol[1]: [location:3333 abc street]
Scol[2]: [country:usa]
我正在使用这个正则表达式:
(.+?)(\\s+(?=(?:(?:[^\"]*\"){2})*[^\"]*$)|$)
现在把它分解成更小的块。
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
简而言之:这意味着匹配1个或更多长度的任何字符后跟“空格或字符串结尾”。空格必须后跟偶数DQ 。因此,双引号外的空格将匹配,并且内部双引号将不匹配(因为这些后面跟着奇数DQ )。
答案 1 :(得分:2)
StringTokenizer对于这项工作来说太简单了。如果您不需要在值内处理引号,可以尝试使用此正则表达式:
String s = "\"Name\":\"jon\" \"location\":\"3333 abc street\" \"country\":\"usa\"";
Pattern p = Pattern.compile("\"([^\"]*)\"");
Matcher m = p.matcher(s);
while (m.find()) {
System.out.println(m.group(1));
}
输出:
名称
乔恩
位置
3333 abc street
国家
USA
这不会处理值中的内部引号 - 输出应该是,例如,
姓名:Fred(“弗雷迪”)琼斯
答案 2 :(得分:1)
你可以使用Json,它看起来像你正在使用Json类型的架构。 做一点谷歌并尝试实施Json。
String sentence=""Name":"jon" "location":"3333 abc street" "country":"usa"" etc
将是Json中的关键,值对,如名称是关键,Jon是值。位置是关键,3333 abc街道是有价值的。等等....
试一试。 这是一个链接 http://www.mkyong.com/java/json-simple-example-read-and-write-json/
编辑: 它只是有点愚蠢的答案,但你可以尝试这样的事情, sentence = sentence.replaceAll(“\”“,”“); StringTokenizer tokens = new StringTokenizer(sentence,“”);