将系统日志转换为 csv ma​​cOS

Convert system log to csv macOS

给定日志行

Sep 25 20:10:44 Evans-MacBook-Pro-2 com.apple.xpc.launchd[1] (com.oracle.oss.mysql.mysqld[50806]): Service could not initialize: Unable to set current working directory. error = 2: No such file or directory, path = /usr/local/mysql: 19H114: xpcproxy + 14537 [673][F3151671-4794-3393-AF04-C3421B7647F3]: 0x2

我想将其转换为 csv 文件,这样 csv 的格式如下:

DATE, SYSTEM, SERVICE, MESSAGE
Sep 25 20:10:44, macbook, com.apple.xpc.launchd[1], (com.oracle.oss.mysql.mysqld[50806]): Service could not initialize: Unable to set current working directory. error = 2: No such file or directory, path = /usr/local/mysql: 19H114: xpcproxy + 14537 [673][F3151671-4794-3393-AF04-C3421B7647F3]: 0x2

这里棘手的部分是消息可以包含逗号。我从命令开始

cat system.log | grep error 

并从这里开始建设。这几乎完成了

grep error system.log \
| while IFS=' ' read d1 d2 d3 sys svc msg; do
    printf '%s, %s, %s, "%s"\n' "$d1 $d2 $d3" $sys $svc "${msg//\"/\"\"}"
done

唯一的问题是解析消息

这是在 zshbash 中执行此操作的一种方法:

printf 'DATE, SYSTEM, SERVICE, MESSAGE\n'
grep error system.log \
| while IFS=' ' read d1 d2 d3 sys svc msg; do
    printf '%s, %s, %s, "%s"\n' "$d1 $d2 $d3" $sys $svc "${msg//\"/\"\"}"
done

此脚本基于一些假设:

  • 日期、系统和服务字段没有嵌入 space 除了示例中显示的内容。
  • csv 文件的使用者可以处理用于消息字段的引用。

在 .csv 文件中支持逗号的标准方法是用双引号将字段括起来,然后通过重复双引号来转义双引号。 csv 文件上的维基百科条目有更多信息:https://en.wikipedia.org/wiki/Comma-separated_values

虽然这样的引用很常见,但绝不是普遍的。如果 csv 消费者无法处理引用的文件,一个简单的答案是将逗号更改为分号:

print 'DATE, SYSTEM, SERVICE, MESSAGE'
grep error system.log \
| while IFS=' ' read -A fl; do
    ary=("$fl[1,3]" "$fl[4]" "$fl[5]" "${fl[6,-1]//,/;}")
    print ${(j:, :)ary}
done

请注意,此版本使用一些特定于 zsh 的语法:printread -A 来为数组赋值(它还将连续的 space 折叠成单个 space), 和 j (join) 参数扩展标志。


已添加:某些 'csv' 文件的使用者可能会更好地使用制表符分隔符。
这是 zsh:

中的一个简单更改
printf 'DATE\tSYSTEM\tSERVICE\tMESSAGE\n'
grep error system.log \
| while IFS=' ' read d1 d2 d3 sys svc msg; do
    ary=("$d1 $d2 $d3" "$sys" "$svc" "$msg")
    print ${(pj:\t:)ary}
done