使用垂直空白字符作为java扫描程序定界符,在每个端点扫描空字符串

使用垂直空白字符作为java扫描程序定界符,在每个端点扫描空字符串,java,regex,java.util.scanner,Java,Regex,Java.util.scanner,我正在尝试使用Java中的Scanner类扫描一个文件,其中的数据字段由“@”或“endline”分隔。以下是一个示例输入文件: Student @ Codey @ Huntting Student @ Sarah @ Honsinger 为了正确地扫描这样的输入文件,我尝试将Java扫描程序上的分隔符更改为正则表达式“[@\\v]”,它应该匹配@或任何垂直空白,包括\n和\r,根据 下面是我用来测试它的代码: Scanner Scanner=新的扫描仪(新文件(“data/initializ

我正在尝试使用Java中的Scanner类扫描一个文件,其中的数据字段由“@”或“endline”分隔。以下是一个示例输入文件:

Student @ Codey @ Huntting
Student @ Sarah @ Honsinger
为了正确地扫描这样的输入文件,我尝试将Java扫描程序上的分隔符更改为正则表达式
“[@\\v]”
,它应该匹配
@
或任何垂直空白,包括
\n
\r
,根据

下面是我用来测试它的代码:

Scanner Scanner=新的扫描仪(新文件(“data/initialize.txt”);
int-tokenNum=0;
scanner.useDelimiter(“[@\\v]”);
while(scanner.hasNext()){
System.out.println(“Token#“+tokenNum+++”:“+scanner.next());
}
scanner.close();
我希望扫描的令牌包括:

Token #1: Student
Token #2:  Codey 
Token #3:  Huntting
Token #4: Student
Token #5:  Sarah
Token #6:  Honsinger
但实际收到的代币是:

Token #1: Student
Token #2:  Codey 
Token #3:  Huntting
Token #4
Token #5: Student
Token #6:  Sarah
Token #7:  Honsinger
Token #8: 
我本以为扫描器在扫描
hunting
时,会在搜索之后向上移动到换行符,并且在下一次调用
input.next()
时,跳过该换行符,但由于某种原因,扫描器似乎在该行的末尾捕获了一个空字符串


我检查了多次,文件在任何一行之后都没有空格。我尝试过不同的模式,如
[@[\\v]]]
[@][\\v]
,但这些模式总是给出具有相同空字符串错误的数据,或者输出完全不正常。

如果我理解正确,我们可能只想删除
@
和一个空格,然后将其替换为新行,并在其前面追加文本。也许,这个表达会有帮助:

([\S\s]*?)(?:@\s|$)

正则表达式 如果不需要此表达式,可以在中修改/更改表达式

正则表达式电路 您还可以在以下位置可视化您的表达式:

JavaScript演示 此代码段显示我们可能有一个有效的表达式:

const regex=/([\S\S]*?)(?:@\S|$)/gm;
const str=`Student@Codey@hunting
学生@Sarah@Honsinger`;
常量subst=`\n$1`;
//被替换的值将包含在结果变量中
const result=str.replace(regex,subst);

log('替换结果:',结果)如果我理解正确,我们可能只想删除
@
和后面的空格,然后用新行替换它并在它前面附加一个文本。也许,这个表达会有帮助:

([\S\s]*?)(?:@\s|$)

正则表达式 如果不需要此表达式,可以在中修改/更改表达式

正则表达式电路 您还可以在以下位置可视化您的表达式:

JavaScript演示 此代码段显示我们可能有一个有效的表达式:

const regex=/([\S\S]*?)(?:@\S|$)/gm;
const str=`Student@Codey@hunting
学生@Sarah@Honsinger`;
常量subst=`\n$1`;
//被替换的值将包含在结果变量中
const result=str.replace(regex,subst);

log('替换结果:',结果)您的文件可能包含格式为
\r\n
的换行符。 在这种情况下,扫描仪会找到分隔符
\r
,并输出
\r
之前的任何内容。然后它找到分隔符
\n
,并在
\r
\n
之间输出空标记,然后在
\n
之后继续

为了允许
\r\n
中断,我建议您将
\r\n |[@\v]
按该确切顺序作为分隔符regex。当然,在转义之后,它会变成
“\r\n|[@\\v]”


正如Andreas提到的,您可以使用的另一个正则表达式是
@\R
,因为
\R
匹配任何unicode换行符,包括
\R\n
。这可能是最好的解决方案。

您的文件可能包含格式为
\r\n
的换行符。 在这种情况下,扫描仪会找到分隔符
\r
,并输出
\r
之前的任何内容。然后它找到分隔符
\n
,并在
\r
\n
之间输出空标记,然后在
\n
之后继续

为了允许
\r\n
中断,我建议您将
\r\n |[@\v]
按该确切顺序作为分隔符regex。当然,在转义之后,它会变成
“\r\n|[@\\v]”


正如Andreas提到的,您可以使用的另一个正则表达式是
@\R
,因为
\R
匹配任何unicode换行符,包括
\R\n
。这可能是最好的解决方案。

您的问题是换行符是一对
\r\n
对,并且
\v
分别匹配它们。为了复制这一点,让我们将代码更改为对测试数据使用内联字符串:

String input = "Student @ Codey @ Huntting\r\n" +
               "Student @ Sarah @ Honsinger\r\n";
try (Scanner scanner = new Scanner(input).useDelimiter("[@\\v]")) {
    for (int tokenNum = 0; scanner.hasNext(); tokenNum++) {
        System.out.println("Token #" + tokenNum + ": \"" + scanner.next() + "\"");
    }
}
输出

Token#0:“学生”
象征物#1:“Codey”
标记2:“狩猎”
令牌#3:“
标记4:“学生”
象征#5:“莎拉”
令牌#6:“Honsinger”
令牌#7:“
解决此问题的一种方法是首先尝试匹配
\r\n
对:

useDelimiter("\r\n|[@\\v]")
输出

Token#0:“学生”
象征物#1:“Codey”
标记2:“狩猎”
标记#3:“学生”
象征4:“莎拉”
象征#5:“荣誉歌手”
但是,这将花费时间检查两次
\r
,因此最好使用内置代码(任何Unicode换行符序列,相当于
\u000D\u000A |[\u000A\u000B\u000C\u000D\u0085\u2028\u2029]
):

相同的结果,但更清楚地反映了您想要匹配的方式


当然,您可以使用
trim()
strip()
删除前导空格和尾随空格,但为什么不让
Scanner
完成这项工作呢?使用
|
需要一个(非捕获)组将其与空白匹配分开:

useDelimiter("\\s*(?:@|\\R)\\s*")
输出

Token#0:“学生”
象征物#1:“Codey”
标记2:“狩猎”
标记#3:“学生”
象征4:“莎拉”
象征#5:“荣誉歌手”

您的问题是换行符是一对
\r\n
对,并且
\v
分别匹配它们。答复