在Java中解析带引号的文本

5
有没有简单的方法将带引号的文本解析成Java字符串?我有这样的行要解析:
author="Tolkien, J.R.R." title="The Lord of the Rings"
publisher="George Allen & Unwin" year=1954 

我只需要Tolkien, J.R.R.的《指环王》,George Allen & Unwin, 1954这些字符串。


你可以尝试使用Javascript正则表达式。 - Wylie
@Ryan:我的错误。但是正则表达式肯定是一种解决方法。 - Wylie
1
@David,您能否告诉我们哪个答案对您最有帮助,并将其选为最佳答案? - Ryan Amos
3个回答

5

您可以使用正则表达式,例如

"(.+)"

它将匹配引号之间的任何字符。在Java中应该是:

Pattern p = Pattern.compile("\\"(.+)\\"";
Matcher m = p.matcher("author=\"Tolkien, J.R.R.\"");
while(matcher.find()){
  System.out.println(m.group(1));      
}

请注意使用group(1),这是第二个匹配项,第一个匹配项group(0)是带引号的完整字符串。
当然,您也可以使用子字符串来选择除第一个和最后一个字符之外的所有内容:
String quoted = "author=\"Tolkien, J.R.R.\"";
String unquoted;    
if(quoted.indexOf("\"") == 0 && quoted.lastIndexOf("\"")==quoted.length()-1){
    unquoted = quoted.substring(1, quoted.lenght()-1);
}else{
  unquoted = quoted;
}

我同意正则表达式确实很让人头疼,但如果你经常使用字符串,了解它绝对是值得的。一个好的起点是perl regex文档: http://perldoc.perl.org/perlre.html - Ben
1
你可以通过使用回顾后发和前瞻来大大简化你的代码,而不是捕获周围的双引号。 - Bohemian

3
有些花哨的模式匹配正则表达式的东西,是一些喜欢用的高级程序员们所喜欢的。
我喜欢用String.split()。它是一个简单的函数,可以满足你的需求。
所以,如果我有一个字符串word: "hello",我想要取出"hello",我可以这样做: myStr = string.split("\"")[1]; 这将根据引号切割字符串。
如果我想更具体一些,我可以这样做: myStr = string.split("word: \"")[1].split("\"")[0]; 这样我就可以使用word: ""来切割了。
当然,如果word: "重复两次,你会遇到问题,这就是模式的作用。我不认为你需要为你的特定问题解决这个问题。
此外,要注意像.和.这样的字符。Split使用正则表达式,所以这些字符会触发有趣的行为。我认为"\\"= \会逃脱这些有趣的规则。如果我错了,请纠正我。
祝你好运!

@david :D 没问题。正则表达式也让我感到困惑。它有更多的潜力,但这个方法对于90%的情况已经足够好了。如果你喜欢我的回答,能否将其标记为最佳答案? - Ryan Amos
split()函数需要一个正则表达式作为参数,因此在使用像"."(点)和任何类型的括号这样的正则表达式具有特殊含义的字符时要小心。 - Philipp Reichart
@Philipp 这就是我回答的后半部分所讨论的内容。 - Ryan Amos
@Ryan 哦,没看到。谢谢 :) - Philipp Reichart

1

你能假设你的文档格式良好且不包含语法错误吗?如果是这样,那么你只需要在使用String.split()后关注其他每个标记。

如果你需要更强大的功能,可能需要使用Scanner类(或者StringBuffer和for循环 ;-))来挑选出有效的标记,并考虑除了“我看到引号”之外的其他条件。

例如,你可能需要比盲目地在引号上分割字符串更强大的解决方案的一些原因:也许只有在引号开始它的等号紧随其后时才是有效的标记。或者,你确实需要处理未引用的值以及引用的值吗?\"需要被视为转义引号吗,还是算作字符串的结尾。它可以是单引号或双引号(例如:HTML),还是总是正确格式化为双引号?

一种强大的方法是像编译器一样思考,并使用基于Java的Lexer(例如JFlex),但这可能对您所需的内容过于复杂。

如果您喜欢低级方法,可以使用while循环逐个字符地迭代输入流,并在看到="时开始将字符复制到StringBuffer中,直到找到另一个非转义的",要么将其连接到各种想要解析的值,要么将它们添加到某种列表中(取决于您计划如何处理数据)。然后继续阅读,直到再次遇到起始标记(例如:="),并重复此过程。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接