在Java中parsingstring有哪些不同的方法?
为了parsing玩家命令,我经常使用split方法通过分隔符来分割一个string,然后通过一系列的if
或者switch
来找出其余的。 在Java中parsingstring有什么不同的方法?
我假设你试图使命令界面尽可能宽容。 如果是这样的话,我build议你使用类似这样的algorithm:
- 阅读string
- 将string拆分为令牌
- 使用字典将同义词转换为常见的forms
- 例如,将“打”,“打”,“打”和“踢”转换为“打”
- 在无序的包容性基础上执行操作
- 无序 – “在脸上打猴子”和“猴子脸上的脸”是一回事,
- 包容性 – 如果命令是“殴打猴子的脸”,他们提供“打孔猴子”,你应该检查这匹配的命令。 如果只有一个命令,请执行此操作。 拥有指挥优先权甚至可能是一个好主意,即使有匹配,也会执行最高行动。
我真的很喜欢正则expression式。 只要命令string相当简单,您可以编写几个正则expression式,这些正则expression式可能需要几页代码才能手动parsing。
我build议你查看http://www.regular-expressions.info ,了解正则expression式,以及Java的具体示例。
手动parsing是很有趣的…在开始:)
在实践中,如果命令不是非常复杂的话,你可以像命令行解释器中那样对待它们。 有一个你可以使用的库列表: http : //java-source.net/open-source/command-line 。 我想你可以从apache commons CLI或args4j开始 (使用注释)。 他们是有据可查的,使用起来非常简单。 他们自动处理parsing,唯一需要做的就是读取对象中的特定字段。
如果你有更复杂的命令,那么创build一个正式的语法将是一个更好的主意。 有一个非常好的图书馆,graphics编辑器,debugging器和语法解释器。 它被称为ANTLR (和编辑ANTLRWorks ),它是免费的:)也有一些例子语法和教程。
Sun本身build议远离StringTokenizer并使用String.spilt方法。
你也想看看Pattern类。
我会看看Zork的 Java迁移 ,并倾向于一个简单的自然语言处理器 (通过标记化或正则expression式驱动),比如下面的(从这个链接):
public static boolean simpleNLP(String inputline,String keywords []) { int i; int maxToken = keywords.length; 从...到 if(inputline.length()= inputline.length())返回false; //检查空白和空行 while(to> = 0) { to = inputline.indexOf('',from); 如果(> 0){ lexed.addElement(inputline.substring(从,到)); 从=到; while(inputline.charAt(from)=='' && from = keywords.length){status = true; 打破;} } } 退货状态; }
…
任何让程序员再次看Zork的理由在我的书里都是好的,只要注意Grues。
…
另一个投票ANTLR / ANTLRWorks。 如果您创build了两个版本的文件,一个是用于实际执行命令的Java代码,另一个是没有(只有语法)的文件,那么您有一个可执行的语言规范,这对testing非常有用, ,如果你决定移植它,那么这是一个很大的时间。
如果这是parsing命令行,我会build议使用Commons Cli 。
Apache Commons CLI库提供了一个用于处理命令行界面的API。
尝试JavaCC Java的parsing器生成器。
它有很多解释语言的function,并且在Eclipse上得到很好的支持。
@CodingTheWheelinheritance你的代码,有点清理并通过eclipse( ctrl + shift + f )插入回来:)
包括每行前面的四个空格。
public static boolean simpleNLP(String inputline, String keywords[]) { if (inputline.length() < 1) return false; List<String> lexed = new ArrayList<String>(); for (String ele : inputline.split(" ")) { lexed.add(ele); } boolean status = false; to = 0; for (i = 0; i < lexed.size(); i++) { String s = (String) lexed.get(i); if (s.equalsIgnoreCase(keywords[to])) { to++; if (to >= keywords.length) { status = true; break; } } } return status; }
一个简单的string标记在空间应该工作,但有很多方法可以做到这一点。
这是一个使用标记器的例子:
String command = "kick person"; StringTokenizer tokens = new StringTokenizer(command); String action = null; if (tokens.hasMoreTokens()) { action = tokens.nextToken(); } if (action != null) { doCommand(action, tokens); }
然后令牌可以进一步用于参数。 这一切都假设参数中没有空格…所以你可能想要推出你自己的简单的parsing机制(如获取第一个空白,并使用前面的文本作为行动,或使用正则expression式,如果你不介意速度打击),只是抽象出来,所以它可以在任何地方使用。
当命令的分隔符string全是相同的string或字符(比如“;”)时,build议您使用StrinkTokenizer类:
StringTokenizer的
但是当分隔符变化或复杂时,build议您使用正则expression式,至less1.4可以被String类自身使用。 它使用java.util.regex包中的Pattern类
模式
如果这种语言像刚刚那样简单
动词名词
然后用手分开效果很好。
如果更复杂一些,你应该看看像ANTLR或JavaCC这样的工具。
我在http://javadude.com/articles/antlrtut上有一个关于ANTLR(v2)的教程,它会告诉你它是如何工作的。;
JCommander似乎相当不错,虽然我还没有testing它。
如果你的文本包含一些分隔符,那么你可以使用你的split
方法。
如果文本包含不规则string,则表示格式不同,则必须使用regular expressions
。
split方法可以将一个string拆分成指定的子stringexpression式regex
的数组。 它的参数有两种forms,即:split( String regex
)和split( String regex, int limit
),其中split( String regex
)实际上是通过调用split(String regex,int limit)来实现的, limit是0 。 那么,当极限> 0和极限<0代表什么?
当jdk解释:当limit> 0时,子数组长度达到限制,也就是说,如果可能的话,可以将limit-1细分,剩下作为子string(除了limit-1时, ;
限制<0表示对arrays的长度没有限制;
limit = 0string结尾的空string将被截断。 StringTokenizer
类是出于兼容性的原因,并保留旧类,所以我们应该尝试使用String类的split方法。 请参阅链接