正则表达式标记日志行
Regex to tokenize log line
我的日志行如下:
[2021-03-10 00:13:32.901] [DefaultDispatcher-worker-2 @coroutine#3] [DEBUG] [4231c006d9083a302fce59d5f0957226] [42c5ac3c0acfc68d] [GreeterImpl] Hello John
这是 []
中的 6 个文本块,然后是其余部分。我正在寻找一个正则表达式来提取 []
内以及末尾的文本。 []
中的文本块可以为空。
我尝试了 (?:\[([^\[\]]*)\])+([^\[\]]+)
,但它只匹配 []
中的第一个块。我也试过 (?:(?<=\[)[^\[\]]*(?=\]))+([^\[\]]+)
但不匹配。
FWIW,正则表达式将在 Java 中实现。
简短编辑: 这个稍微简单的正则表达式也可以工作:
(?:(?<=\[)[^\[\]]*)|(?:(?<=\])[^\[\]]*$)
我从你自己的评论中提取了它。
原回答如下。
TL;DR
(?:(?<=^\[| \[)[^\[\]]*)|(?:(?<=\] )[^\[\]]*$)
说明:两部分用|
、“或”分隔。
- 第一部分,
(?:(?<=^\[| \[)[^\[\]]*)
匹配方括号内的内容。接近末尾的 [^\[\]]*
匹配最长可能的 运行 个既不是 [
也不是 ]
的字符。 (?<=^\[| \[)
要求它在字符串开头和 [
或 [
之前。最后我把整个东西放到一个非捕获组中以确保后视优先于 |
.
- 第二部分
(?:(?<=\] )[^\[\]]*$)
匹配日志行末尾方括号外的内容(示例中的 Hello John
)。这次非括号的运行前面必须有]
,后面有行尾
查看实际效果:
On regex101 我建的地方
在Java:
String logLine = "[2021-03-10 00:13:32.901]"
+ " [DefaultDispatcher-worker-2 @coroutine#3] [DEBUG]"
+ " [4231c006d9083a302fce59d5f0957226] [42c5ac3c0acfc68d]"
+ " [GreeterImpl] Hello John";
Matcher m = Pattern
.compile("(?:(?<=^\[| \[)[^\[\]]*)|(?:(?<=\] )[^\[\]]*$)")
.matcher(logLine);
while (m.find()) {
System.out.println(m.group());
}
输出为:
2021-03-10 00:13:32.901
DefaultDispatcher-worker-2 @coroutine#3
DEBUG
4231c006d9083a302fce59d5f0957226
42c5ac3c0acfc68d
GreeterImpl
Hello John
不同的想法:String.split()
String[] tokens = logLine.split("\] \[|\] (?!\[)");
assert tokens[0].startsWith("[") : logLine;
tokens[0] = tokens[0].substring(1);
for (String token : tokens) {
System.out.println(token);
}
输出与之前相同。
我在 ] [
或 ]
而不是 之后拆分 [
(最后一次拆分)。它使第一个 [
完好无损,所以我必须单独删除它,这不太好。否则我发现它比其他解决方案更容易理解。
另一种选择是使用 \G
锚点来匹配开头的 [...]
部分,以及可选的第 2 组中的其余部分。
这样你就可以区分哪些部分在方括号之间,哪些部分在其余部分。
\G\[([^][]*)]\h+([^][]+$)?
模式匹配:
\G
断言位置在前一个匹配的末尾或在第一个匹配的字符串的开头
\[
匹配 [
(
捕获 组 1
[^][]*
匹配 0+ 次出现或除 [
或 ]
之外的任何字符
)
关闭组 1
]\h+
匹配结尾 ]
和 1 个或多个水平空白字符
(
捕获 第 2 组
[^][]+$
匹配除 [
或 ]
之外的任何字符出现 1 次以上
)?
关闭组 2 并将其设为可选
在 Java 中带有双反斜杠
String regex = "\G\[([^\]\[]*)]\h+([^\]\[]+$)?";
我的日志行如下:
[2021-03-10 00:13:32.901] [DefaultDispatcher-worker-2 @coroutine#3] [DEBUG] [4231c006d9083a302fce59d5f0957226] [42c5ac3c0acfc68d] [GreeterImpl] Hello John
这是 []
中的 6 个文本块,然后是其余部分。我正在寻找一个正则表达式来提取 []
内以及末尾的文本。 []
中的文本块可以为空。
我尝试了 (?:\[([^\[\]]*)\])+([^\[\]]+)
,但它只匹配 []
中的第一个块。我也试过 (?:(?<=\[)[^\[\]]*(?=\]))+([^\[\]]+)
但不匹配。
FWIW,正则表达式将在 Java 中实现。
简短编辑: 这个稍微简单的正则表达式也可以工作:
(?:(?<=\[)[^\[\]]*)|(?:(?<=\])[^\[\]]*$)
我从你自己的评论中提取了它。
原回答如下。
TL;DR
(?:(?<=^\[| \[)[^\[\]]*)|(?:(?<=\] )[^\[\]]*$)
说明:两部分用|
、“或”分隔。
- 第一部分,
(?:(?<=^\[| \[)[^\[\]]*)
匹配方括号内的内容。接近末尾的[^\[\]]*
匹配最长可能的 运行 个既不是[
也不是]
的字符。(?<=^\[| \[)
要求它在字符串开头和[
或[
之前。最后我把整个东西放到一个非捕获组中以确保后视优先于|
. - 第二部分
(?:(?<=\] )[^\[\]]*$)
匹配日志行末尾方括号外的内容(示例中的Hello John
)。这次非括号的运行前面必须有]
,后面有行尾
查看实际效果:
On regex101 我建的地方
在Java:
String logLine = "[2021-03-10 00:13:32.901]" + " [DefaultDispatcher-worker-2 @coroutine#3] [DEBUG]" + " [4231c006d9083a302fce59d5f0957226] [42c5ac3c0acfc68d]" + " [GreeterImpl] Hello John"; Matcher m = Pattern .compile("(?:(?<=^\[| \[)[^\[\]]*)|(?:(?<=\] )[^\[\]]*$)") .matcher(logLine); while (m.find()) { System.out.println(m.group()); }
输出为:
2021-03-10 00:13:32.901 DefaultDispatcher-worker-2 @coroutine#3 DEBUG 4231c006d9083a302fce59d5f0957226 42c5ac3c0acfc68d GreeterImpl Hello John
不同的想法:String.split()
String[] tokens = logLine.split("\] \[|\] (?!\[)");
assert tokens[0].startsWith("[") : logLine;
tokens[0] = tokens[0].substring(1);
for (String token : tokens) {
System.out.println(token);
}
输出与之前相同。
我在 ] [
或 ]
而不是 之后拆分 [
(最后一次拆分)。它使第一个 [
完好无损,所以我必须单独删除它,这不太好。否则我发现它比其他解决方案更容易理解。
另一种选择是使用 \G
锚点来匹配开头的 [...]
部分,以及可选的第 2 组中的其余部分。
这样你就可以区分哪些部分在方括号之间,哪些部分在其余部分。
\G\[([^][]*)]\h+([^][]+$)?
模式匹配:
\G
断言位置在前一个匹配的末尾或在第一个匹配的字符串的开头\[
匹配[
(
捕获 组 1[^][]*
匹配 0+ 次出现或除[
或]
之外的任何字符
)
关闭组 1]\h+
匹配结尾]
和 1 个或多个水平空白字符(
捕获 第 2 组[^][]+$
匹配除[
或]
之外的任何字符出现 1 次以上
)?
关闭组 2 并将其设为可选
在 Java 中带有双反斜杠
String regex = "\G\[([^\]\[]*)]\h+([^\]\[]+$)?";