[ 和 ] 字符以外的空白定界符的正则表达式

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.