1、解释下如下配置
bash
filter {
ruby {
code => '
msg = event.get("message")
if msg
msg = msg.gsub(/\x1B\[[0-?]*[ -\/]*[@-~]/, "")
event.set("message", msg)
end
'
}
}
这是 Logstash pipeline 的 filter 配置 ,用 Ruby 代码把日志里的 ANSI 颜色控制符(比如带颜色的终端输出)清理掉。
逐行解释如下👇
✅ 配置整体结构
filter {
ruby {
code => ' ... Ruby 脚本 ... '
}
}
意思:
-
filter { ... }- Logstash 处理事件阶段
-
ruby { ... }- 使用 Ruby 插件执行自定义逻辑
-
code => ' ... '- Ruby 代码写在单引号字符串里
🧠 代码逻辑拆解
代码内容:
ruby
msg = event.get("message")
if msg
msg = msg.gsub(/\x1B\[[0-?]*[ -\/]*[@-~]/, "")
event.set("message", msg)
end
逐句解释:
1️⃣ 取日志字段
msg = event.get("message")
从 Logstash 事件中获取 message 字段
(也就是 Filebeat 发过来的原始日志内容)
2️⃣ 判断 message 是否存在
if msg
避免 message 为空时报错
3️⃣ 正则删除 ANSI 转义字符
msg = msg.gsub(/\x1B\[[0-?]*[ -\/]*[@-~]/, "")
这一行是关键:
-
\x1B= ESC 字符 -
\[[0-?]*[ -\/]*[@-~]-
标准 ANSI 控制码格式
-
如:
\u001b[31m(红色)\u001b[0m\u001b[1;32m- etc
-
👉 作用:去掉日志里的颜色和控制字符
4️⃣ 把清洗后的值写回
event.set("message", msg)
覆盖原 message 字段
现在 ES/Kibana 里看到的就是干净的日志
🎯 实际解决的问题
很多容器 / Python / Java 应用日志启用了彩色输出,例如:
^[[32mINFO^[[0m Service started
在 Kibana 里很恶心,还可能导致解析失败
这个 ruby 过滤器就是用来:
✔️ 去掉 ^[[32m ^[[0m
✔️ 保留纯文本内容
✅ 你现在的结构写得是正确的
filter {
ruby {
code => '...'
}
}
这是标准写法 👍
如果你还想扩展:
- 只对某些索引清理
- 或者 message 换成 log 字段
- 或想用 mutate/gsub 替代 ruby
我也可以帮你优化版本 👌
2、msg = msg.gsub(/\x1B\[[0-?]*[ -\/]*[@-~]/, "") 详细解释下这个
很好,这一行是整个配置里"最有技术含量"的地方 👇
ruby
msg = msg.gsub(/\x1B\[[0-?]*[ -\/]*[@-~]/, "")
作用:
把终端 ANSI 转义控制序列(颜色 / 高亮 / 光标控制等)全部删除
一、整体结构先看懂
Ruby 的 gsub:
gsub(正则, 替换内容)
意思:
把字符串里 所有匹配该正则的内容替换为空字符串
➡️ 所以这行代码是:删除 ANSI 控制码
二、正则逐段拆解(最关键)
完整正则:
\x1B\[[0-?]*[ -\/]*[@-~]
ANSI 控制序列的标准格式叫 CSI(Control Sequence Introducer)
一般长这样:
ESC [ parameters ; more params command
例如:
\x1b[31m
\x1b[0m
\x1b[1;32m
\x1b[1;31;40m
\x1b[2J
\x1b[H
这正则就是 专门为 CSI 这种格式写的。
1️⃣ \x1B
\x1B
十六进制 1B → ESC 字符
也可以写成:
\u001b
\033
👉 说明:所有 ANSI 控制码都以 ESC 开头
2️⃣ \[
\[
字面意义的 [
(CSI 开头是 ESC + [)
3️⃣ [0-?]*
[0-?]*
这一段允许:
0 1 2 ... 9 ; < = > ?
也就是 ANSI 参数部分:
3101;3238;5;12?25h- 等等
👉 用 * 表示 0 个或多个参数字符
4️⃣ [ -\/]*
[ -\/]*
这个字符范围比较怪,看起来难,其实是:
- ASCII 32(空格) 到
/(47)
也就是 ANSI 里的 intermediate bytes 区间
某些控制序列会用到这一段
例如:
ESC [ ? 25 h
ESC [ > 5 m
👉 仍然是 * 表示 可选 & 多个
5️⃣ 最后一段 [@-~]
[@-~]
这个是:
- ASCII
@到~ - 范围 64 → 126
ANSI 里这叫 Final Byte(命令字符)
常见的:
| 字符 | 含义 |
|---|---|
| m | 颜色 / 样式 |
| H | 光标移动 |
| J | 清屏 |
| K | 清行 |
| A B C D | 光标方向 |
| s / u | 保存/恢复光标 |
| t | 窗口控制 |
👉 只匹配 最后那个命令位
三、举例看它怎么工作
匹配:
\x1b[31m
\x1b[1;32m
\x1b[1;31;40m
\x1b[2J
\x1b[K
\x1b[?25h
\x1b[>5m
都会被整段删掉。
四、为什么不用普通简单正则?
你可能见过别人写:
/\033\[[0-9;]*m/
这个 只能匹配带 m 的颜色控制
但你的日志可能不止颜色,还可能有:
- 光标移动
- 清屏
- 光标隐藏
- 终端行为
- 其他 CSI 控制符
而这一条:
\x1B\[[0-?]*[ -\/]*[@-~]
是 符合 ANSI/VT100 标准的通用匹配表达式,覆盖非常全面,是业界通用方案。
✅ 总结一句
这一行的正则:
👉 精准匹配 所有 ANSI CSI 控制序列
👉 删除日志中终端颜色/控制字符
👉 保留纯文本,保证 ES/Kibana 正常显示
如果你愿意,我还能帮你:
- 改成 Logstash mutate/gsub(不用 ruby)
- 或只删除
m不删光标控制 - 或仅删除特定颜色控制
你用什么日志源?(Java?Python?K8s?)
我可以帮你做最优版本 👍
3、ESC 是啥
这里的 ESC 指的是 Escape 控制字符 ,不是"退出键"本身,而是 ASCII 表中的一个控制字符:
- ASCII 编码:十进制 27
- 十六进制 :
0x1B - 八进制 :
033 - 在正则里写成 :
\x1B
在终端里,彩色输出、光标移动、清屏等所谓 ANSI 转义序列(ANSI Escape Sequences) 都是以这个 ESC 字符开头的,例如:
ESC [ 31m --> 设置前景色为红色
ESC [ 0m --> 重置颜色
写成可见形式就是:
\x1B[31m
\x1B[0m
所以你看到的正则:
\x1B\[[0-?]*[ -\/]*[@-~]
就是:
先匹配 ESC(\x1B),然后匹配 [ 开头,再匹配后面的参数 + 结尾符,从而 整体匹配并删除 ANSI 颜色/控制码。
总结一句:
👉 ESC 是终端控制序列的起始控制字符(ASCII 27),用来触发颜色、光标等控制效果。
4、这个和上边的一样吧,不过使用的是 javascript 脚本
bash
processors:
- script:
lang: javascript
id: remove_ansi
source: >
function process(event) {
var msg = event.Get("message");
if (msg != null) {
msg = msg.replace(/\x1B\[[0-?]*[ -/]*[@-~]/g, "");
event.Put("message", msg);
}
}
完全一样,功能上 和上面 Ruby 版本是一致的 ,只是写法换成了 JavaScript(Filebeat / Logstash Processor 支持 JS 语言脚本)。
逐行对比解释:
原 Ruby 版本
ruby
msg = event.get("message")
if msg
msg = msg.gsub(/\x1B\[[0-?]*[ -\/]*[@-~]/, "")
event.set("message", msg)
end
JavaScript 版本
javascript
function process(event) {
var msg = event.Get("message");
if (msg != null) {
msg = msg.replace(/\x1B\[[0-?]*[ -/]*[@-~]/g, "");
event.Put("message", msg);
}
}
对比说明
| 功能 | Ruby | JS (Filebeat) |
|---|---|---|
| 取 message | event.get("message") |
event.Get("message") |
| 判断非空 | if msg |
if (msg != null) |
| 替换 ANSI码 | msg.gsub(正则, "") |
msg.replace(正则, "") + g |
| 写回 message | event.set("message", msg) |
event.Put("message", msg) |
🔑 注意点
-
正则几乎一模一样
/\x1B\[[0-?]*[ -/]*[@-~]/g\x1B→ ESC[0-?]*[ -/]*[@-~]→ 匹配 ANSI 控制序列g→ 全局匹配(Ruby 的gsub默认全局)
-
大小写
- JS 中
event.Get和event.Put是 Filebeat 内置方法,首字母大写 - Ruby 是小写
get/set
- JS 中
-
功能效果
- 删除所有 ANSI 转义序列
- 保留纯文本日志
- 方便 Kibana/ES 展示
✅ 总结
- 功能上完全等价
- 只是语言不同:Ruby 版本适合 Logstash filter 插件,JS 版本适合 Filebeat
scriptprocessor - 两者都可以用来清理终端彩色输出
如果你愿意,我可以帮你写一个 同时支持多种日志格式 + JS 去 ANSI 的 Filebeat 脚本示例,直接可用。
你希望我写吗?