我希望有以下字符串
!cmd 45 90 "An argument" Another AndAnother "Another one in quotes"
Run Code Online (Sandbox Code Playgroud)
成为以下阵列
{ "!cmd", "45", "90", "An argument", "Another", "AndAnother", "Another one in quotes" }
Run Code Online (Sandbox Code Playgroud)
我试过了
new StringTokenizer(cmd, "\"")
Run Code Online (Sandbox Code Playgroud)
但这将返回"另一个"和"和另一个"另一个和另一个"这不是预期的效果.
谢谢.
编辑:我再次改变了这个例子,这次我认为它解释了最好的情况,尽管它与第二个例子没有什么不同.
pol*_*nts 52
在这些场景中使用a java.util.regex.Matcher并执行find()而不是任何类型更容易split.
也就是说,不是为标记之间的分隔符定义模式,而是定义标记本身的模式.
这是一个例子:
String text = "1 2 \"333 4\" 55 6 \"77\" 8 999";
// 1 2 "333 4" 55 6 "77" 8 999
String regex = "\"([^\"]*)\"|(\\S+)";
Matcher m = Pattern.compile(regex).matcher(text);
while (m.find()) {
if (m.group(1) != null) {
System.out.println("Quoted [" + m.group(1) + "]");
} else {
System.out.println("Plain [" + m.group(2) + "]");
}
}
Run Code Online (Sandbox Code Playgroud)
以上打印(如ideone.com上所示):
Plain [1]
Plain [2]
Quoted [333 4]
Plain [55]
Plain [6]
Quoted [77]
Plain [8]
Plain [999]
Run Code Online (Sandbox Code Playgroud)
模式基本上是:
"([^"]*)"|(\S+)
\_____/ \___/
1 2
Run Code Online (Sandbox Code Playgroud)
有2个替代品:
请注意,这不会处理引用段中的转义双引号.如果您需要这样做,那么模式会变得更复杂,但Matcher解决方案仍然有效.
请注意,这StringTokenizer是一个遗留类.建议使用java.util.Scanner或者String.split,或者当然java.util.regex.Matcher是最灵活的.
这是老式的方式.创建一个查看for循环中每个字符的函数.如果角色是空格,请将所有内容(不包括空格)取出并添加为数组的条目.注意位置,并再次执行相同的操作,将空格后的下一部分添加到数组中.遇到双引号时,将名为'inQuote'的布尔值标记为true,并在inQuote为true时忽略空格.当inQuote为true时命中引号时,将其标记为false并在遇到空格时返回到破坏状态.然后,您可以根据需要扩展它以支持转义字符等.
这可以用正则表达式完成吗?我想,我不知道.但是整个功能的写入要比这个回复少.
Apache Commons 来救援!
import org.apache.commons.text.StringTokenizer
import org.apache.commons.text.matcher.StringMatcher
import org.apache.commons.text.matcher.StringMatcherFactory
@Grab(group='org.apache.commons', module='commons-text', version='1.3')
def str = /is this 'completely "impossible"' or """slightly"" impossible" to parse?/
StringTokenizer st = new StringTokenizer( str )
StringMatcher sm = StringMatcherFactory.INSTANCE.quoteMatcher()
st.setQuoteMatcher( sm )
println st.tokenList
Run Code Online (Sandbox Code Playgroud)
输出:
[是,这,完全“不可能”,还是“稍微”不可能,解析?]
一些注意事项:
@Grab行提供了您需要的依赖行类型的线索(例如 in build.gradle)......或者当然只是在您的类路径中包含 .jarStringTokenizer这里不是
java.util.StringTokenizer......正如该import行所示
org.apache.commons.text.StringTokenizerdef str = ...
行是一种String在 Groovy 中生成包含单引号和双引号而无需转义的方法StringMatcherFactory在 apache commons-text 1.3 中可以在这里找到
:如您所见,它INSTANCE可以为您提供一堆不同的StringMatchers。您甚至可以推出自己的:但您需要检查StringMatcherFactory源代码以了解它是如何完成的。PS 为什么使用 Apache Commons 比任何其他解决方案更好?除了没有必要重新发明轮子这一事实之外,我至少可以想到两个原因:
PPS 没有什么迫使您将 Apache 代码视为神秘的“黑匣子”。源代码是开放的,并用通常完全“可访问”的 Java 编写。因此,您可以自由地检查事情是如何做到心满意足的。这样做通常很有启发性。
之后
对 ArtB 的问题非常感兴趣,我查看了来源:
在 StringMatcherFactory.java 中我们看到:
private static final AbstractStringMatcher.CharSetMatcher QUOTE_MATCHER = new AbstractStringMatcher.CharSetMatcher(
"'\"".toCharArray());
Run Code Online (Sandbox Code Playgroud)
……比较沉闷……
因此,我们可以查看 StringTokenizer.java:
public StringTokenizer setQuoteMatcher(final StringMatcher quote) {
if (quote != null) {
this.quoteMatcher = quote;
}
return this;
}
Run Code Online (Sandbox Code Playgroud)
好的...然后,在同一个 java 文件中:
private int readWithQuotes(final char[] srcChars ...
Run Code Online (Sandbox Code Playgroud)
其中包含评论:
// If we've found a quote character, see if it's followed by a second quote. If so, then we need to actually put the quote character into the token rather than end the token.
Run Code Online (Sandbox Code Playgroud)
......我懒得继续追踪线索了。您有一个选择:要么是您的“hackish”解决方案,您在提交字符串以进行标记化之前系统地预处理您的字符串,将 |\\\"|s 转换为 |\"\"|s ...(即您在哪里替换每个 | \" | with | "" |)...
或者...您检查 org.apache.commons.text.StringTokenizer.java 以找出如何调整代码。这是一个小文件。我不认为这会那么困难。然后进行编译,本质上是创建 Apache 代码的一个分支。
我不认为它可以配置。但是,如果您找到了一个有意义的代码调整解决方案,您可能会将其提交给 Apache,然后它可能会被接受用于代码的下一次迭代,并且您的名字至少会出现在 Apache 的“功能请求”部分中:可能是kleos 的一种形式,通过它您可以实现编程永生......
| 归档时间: |
|
| 查看次数: |
25010 次 |
| 最近记录: |