[ 和 ] 字符以外的空白定界符的正则表达式
Regex for whitespace delemiter except for [ and ] characters
我认为自己的正则表达式还不错,但这个正则表达式似乎出奇地棘手。
我想要 trim 所有空格,“”和 [] 字符之间的空格除外。
我使用了这个正则表达式 ("[^"]*"|\S+)\s+
但确实将我登录的 [06/Jan/2021:17:50:09 +0300] 部分拆分为两个街区。
这是我的整个日志行:
[06/Jan/2021:17:50:09 +0300] "" 10.139.3.194 407 "CONNECT clients5.google.com:443 HTTP/1.1" "" "-" "" 4245 75 "" "" "81" ""
我使用 sed 命令(用逗号替换空格)基于我的正则表达式得到的结果:
[06/Jan/2021:17:50:09,+0300],"",10.139.3.194,407,"CONNECT clients5.google.com:443 HTTP/1.1","","-","",4245,75,"","","81",""
终于是我想要的结果了:
[06/Jan/2021:17:50:09 +0300],"",10.139.3.194,407,"CONNECT clients5.google.com:443 HTTP/1.1","","-","",4245,75,"","","81",""
您可以通过添加 \[[^][]*]
作为第 1 组模式的替代来匹配方括号之间的字符串:
sed -E 's/(\[[^][]*]|"[^"]*"|\S+)\s+/,/g'
现在,POSIX ERE(使用 -E
选项启用的语法)模式匹配
(\[[^][]*]|"[^"]*"|\S+)
- 第 1 组:要么
\[[^][]*]
- 一个 [
字符,然后是 [
和 ]
以外的零个或多个字符,然后是一个 ]
字符
|
"[^"]*"
- "
字符,除 "
之外的零个或多个字符,然后是 "
字符
|
- 或
\S+
- 一个或多个非空白字符
\s+
- 一个或多个空格
参见 online demo:
#!/bin/bash
s='[06/Jan/2021:17:50:09 +0300] "" 10.139.3.194 407 "CONNECT clients5.google.com:443 HTTP/1.1" "" "-" "" 4245 75 "" "" "81" ""'
sed -E 's/(\[[^][]*]|"[^"]*"|\S+)\s+/,/g' <<< "$s"
输出:
[06/Jan/2021:17:50:09 +0300],"",10.139.3.194,407,"CONNECT clients5.google.com:443 HTTP/1.1","","-","",4245,75,"","","81",""
由于这些示例输入看起来像日志,因此考虑到它们将始终采用相同的格式;有了这个,您可以尝试遵循 awk
代码,在 GNU awk
.
中的示例中编写和测试
awk -v FPAT='[^]]*\]|"[^"]*"|([0-9]+\.){3}[0-9]+|[0-9]{2,4}' -v OFS="," '{=} 1' Input_file
解释:
- 简单的解释就是在这里使用 GNU
awk
。其中有 FPAT
选项可用。
- 以正则表达式形式设置字段分隔符的选项。它按照 FPAT 中提到的正则表达式匹配内容,并在每行相应地制作字段。
- 然后将所有行的
OFS
(输出字段分隔符)设置为 ,
。
- 在
awk
的主程序中重置行(通过重置第一个字段)以根据 OP 的要求将 OFS 值应用于它。这将确保逗号只应根据需要出现在输出中。
正则表达式解释:
[^]]*\] ##Matching everything till ] followed by ] here.
| ##OR
"[^"]*" ##Matching from " till first occurrence of " everything between them including "
| ##OR
([0-9]+\.){3}[0-9]+ ##Matching digits followed by dot 3 times followed by digits
| ##OR
[0-9]{2,4} ##Matching 2 to 4 digits here.
我认为自己的正则表达式还不错,但这个正则表达式似乎出奇地棘手。
我想要 trim 所有空格,“”和 [] 字符之间的空格除外。
我使用了这个正则表达式 ("[^"]*"|\S+)\s+
但确实将我登录的 [06/Jan/2021:17:50:09 +0300] 部分拆分为两个街区。
这是我的整个日志行:
[06/Jan/2021:17:50:09 +0300] "" 10.139.3.194 407 "CONNECT clients5.google.com:443 HTTP/1.1" "" "-" "" 4245 75 "" "" "81" ""
我使用 sed 命令(用逗号替换空格)基于我的正则表达式得到的结果:
[06/Jan/2021:17:50:09,+0300],"",10.139.3.194,407,"CONNECT clients5.google.com:443 HTTP/1.1","","-","",4245,75,"","","81",""
终于是我想要的结果了:
[06/Jan/2021:17:50:09 +0300],"",10.139.3.194,407,"CONNECT clients5.google.com:443 HTTP/1.1","","-","",4245,75,"","","81",""
您可以通过添加 \[[^][]*]
作为第 1 组模式的替代来匹配方括号之间的字符串:
sed -E 's/(\[[^][]*]|"[^"]*"|\S+)\s+/,/g'
现在,POSIX ERE(使用 -E
选项启用的语法)模式匹配
(\[[^][]*]|"[^"]*"|\S+)
- 第 1 组:要么\[[^][]*]
- 一个[
字符,然后是[
和]
以外的零个或多个字符,然后是一个]
字符|
"[^"]*"
-"
字符,除"
之外的零个或多个字符,然后是"
字符|
- 或\S+
- 一个或多个非空白字符
\s+
- 一个或多个空格
参见 online demo:
#!/bin/bash
s='[06/Jan/2021:17:50:09 +0300] "" 10.139.3.194 407 "CONNECT clients5.google.com:443 HTTP/1.1" "" "-" "" 4245 75 "" "" "81" ""'
sed -E 's/(\[[^][]*]|"[^"]*"|\S+)\s+/,/g' <<< "$s"
输出:
[06/Jan/2021:17:50:09 +0300],"",10.139.3.194,407,"CONNECT clients5.google.com:443 HTTP/1.1","","-","",4245,75,"","","81",""
由于这些示例输入看起来像日志,因此考虑到它们将始终采用相同的格式;有了这个,您可以尝试遵循 awk
代码,在 GNU awk
.
awk -v FPAT='[^]]*\]|"[^"]*"|([0-9]+\.){3}[0-9]+|[0-9]{2,4}' -v OFS="," '{=} 1' Input_file
解释:
- 简单的解释就是在这里使用 GNU
awk
。其中有FPAT
选项可用。 - 以正则表达式形式设置字段分隔符的选项。它按照 FPAT 中提到的正则表达式匹配内容,并在每行相应地制作字段。
- 然后将所有行的
OFS
(输出字段分隔符)设置为,
。 - 在
awk
的主程序中重置行(通过重置第一个字段)以根据 OP 的要求将 OFS 值应用于它。这将确保逗号只应根据需要出现在输出中。
正则表达式解释:
[^]]*\] ##Matching everything till ] followed by ] here.
| ##OR
"[^"]*" ##Matching from " till first occurrence of " everything between them including "
| ##OR
([0-9]+\.){3}[0-9]+ ##Matching digits followed by dot 3 times followed by digits
| ##OR
[0-9]{2,4} ##Matching 2 to 4 digits here.