我正在使用Scanner类来解析一些文本。也许我的模式是错误的,但是我尝试对其进行调整,但没有找到使其工作的方法,所以我将其发布在这里:
public class StackOverflowExample {
public static void main(String[] args) {
// This is a source string example
StringReader stringReader = new StringReader("\"field_name\":\"field_value\"");
// The scanner instance with default values
Scanner scanner = new Scanner(stringReader);
// Set the scanner delimiter to \b* so it takes blanks as delimiters only if they're there
scanner.useDelimiter(Pattern.compile("\b*"));
// Compile the pattern to match field names
Pattern field_name_pattern = Pattern.compile("\"\\w+\":");
// Check if scanner finds the first field name
if (scanner.hasNext(field_name_pattern)) {
// Field name found, so print it
System.out.println(scanner.next(field_name_pattern));
} else {
// Field name not found, so warn about it
System.out.println("Oops! It didn't work!");
}
}
}
预期的行为是扫描程序与读取器中的第一个“ field_name”:子字符串匹配,因此对扫描程序返回true。hasNext(field_name_pattern),但实际行为是它与之不匹配,因此返回改为false。
答案 0 :(得分:2)
问题出在扫描仪的定界符中,该问题失败,并且将完整的输入字符串作为下一个令牌返回给扫描仪,并导致模式public function getPosts()
{
return $this->hasMany(Post::className(), ['id' => 'post_id'])
->viaTable('post_tag',['tag_id'=>'id']);
}
返回"\"\\w+\":"
。
根据public boolean hasNext(Pattern pattern)
的Javadoc
如果下一个完整令牌与指定的模式匹配,则返回true。完整的令牌由与定界符模式匹配的输入作为前缀和后缀。
您可能希望使用冒号作为分隔符以使其起作用:
false
完整代码:
scanner.useDelimiter(Pattern.compile(":"));
输出:
// This is a source string example
StringReader stringReader = new StringReader("\"field_name\":\"field_value\"");
// The scanner instance with default values
Scanner scanner = new Scanner(stringReader);
// Set the scanner delimiter to \b* so it takes blanks as delimiters only if they're there
scanner.useDelimiter(Pattern.compile(":"));
// Compile the pattern to match field names
Pattern field_name_pattern = Pattern.compile("\"\\w+\"");
// Check if scanner finds the first field name
if (scanner.hasNext(field_name_pattern)) {
// Field name found, so print it
System.out.println(scanner.next(field_name_pattern));
} else {
// Field name not found, so warn about it
System.out.println("Oops! It didn't work!");
}
scanner.close();
答案 1 :(得分:1)
Scanner
将文本分成令牌,然后提供这些令牌或允许您使用这些令牌。分隔符是确定如何将令牌分开的因素。来自Javadoc:
扫描程序使用定界符模式将其输入分为令牌,默认情况下,该模式与空格匹配。然后,可以使用各种下一种方法将生成的令牌转换为不同类型的值。
在您的情况下,分隔符为"\b*"
。使用这样的可选定界符,我不确定Scanner会做什么,但是您的测试表明,它会将无空格的文本拆分为与指定模式不匹配的单个标记。
如果您想为此使用Scanner
,则必须找到一种与您的用例更好地结合的模式。如果这更适合您的用例,那么您也可能只使用正则表达式而不使用扫描器。
答案 2 :(得分:0)
好的,其他用户指出的问题是,当没有具体的定界符时,Scanner.hasNext(Pattern pattern)方法不起作用。实际上,它需要它来生成令牌,否则,整个字符串将成为下一个令牌。
解决方案是改用Scanner.findInLine(Pattern pattern)方法,如下所示:
public class StackOverflowExample {
public static void main(String[] args) {
// This is a source string example
StringReader stringReader = new StringReader("\"field_name\":\"field_value\"");
// The scanner instance with default values
Scanner scanner = new Scanner(stringReader);
// Compile the pattern to match field names
Pattern field_name_pattern = Pattern.compile("\"\\w+\":");
// Check if scanner finds the first field name
String field_name = scanner.findInLine(field_name_pattern);
if (field_name != null) {
// Field name found, so print it
System.out.println(field_name);
} else {
// Field name not found, so warn about it
System.out.println("Oops! It didn't work!");
}
}
}
非常感谢那些回答。