在 Rust 中,如何捕获带有颜色的过程输出?
In Rust, how can I capture process output with colors?
我想从另一个进程(例如 git status
)捕获输出,对其进行处理,然后使用所有样式(粗体、斜体、下划线)和颜色进行打印。进一步处理 String
对我来说非常重要,我 不想 只想打印它。
在 Unix 世界中,我认为这会涉及转义码,我不确定 Windows 世界,但这对我来说也很重要。
我知道没有颜色怎么做:
fn exec_git() -> String {
let output = Command::new("git")
.arg("status")
.output()
.expect("failed to execute process");
String::from_utf8_lossy(&output.stdout).into_owned()
}
也许我应该改用 spawn
?
您可以使用git -c color.status=always status
强制git输出颜色
use std::process::Command;
fn main() {
let output = Command::new("git")
.arg("-c")
.arg("color.status=always")
.arg("status")
.output()
.expect("failed to execute process");
let output = String::from_utf8_lossy(&output.stdout).into_owned();
println!("{}", output);
}
这仅适用于 git status
。对于更通用的解决方案,您要么必须检查程序文档并希望有一种方法可以强制彩色输出,要么检查程序如何确定它是否应该输出颜色(例如检查 COLORTERM
环境变量).
您的代码已经有效:
use std::process::Command;
fn main() {
let output = Command::new("ls")
.args(&["-l", "--color"])
.env("LS_COLORS", "rs=0:di=38;5;27:mh=44;38;5;15")
.output()
.expect("Failed to execute");
let sout = String::from_utf8(output.stdout).expect("Not UTF-8");
let serr = String::from_utf8(output.stderr).expect("Not UTF-8");
println!("{}", sout);
println!("{}", serr);
}
打印输出:
total 68
-rw-r--r-- 4 root root 56158 Dec 23 00:00 [0m[44;38;5;15mCargo.lock[0m
-rw-rw-r-- 4 root root 2093 Dec 9 02:54 [44;38;5;15mCargo.toml[0m
drwxr-xr-x 1 root root 4096 Dec 30 15:24 [38;5;27msrc[0m
drwxr-xr-x 1 root root 4096 Dec 23 00:19 [38;5;27mtarget[0m
请注意,输出中散布着一堆垃圾([44;
、[0m
等)。这些是 ANSI escape codes,终端仿真器解释这些以更改以下文本的颜色。
如果你打印带调试的字符串,你会看到:
\u{1b}[0m\u{1b}[44;38;5;15mCargo.lock\u{1b}[0m
每个转义码都以 ESC
(\u{1b}
) 开头,后跟实际命令。您将不得不解析它们,以便在您进行的任何处理中忽略它们。
Windows 不使用转义码(尽管 maybe it can in Windows 10?), and instead a program directly modifies the console it is connected to。输出中没有任何内容指示颜色。
我想从另一个进程(例如 git status
)捕获输出,对其进行处理,然后使用所有样式(粗体、斜体、下划线)和颜色进行打印。进一步处理 String
对我来说非常重要,我 不想 只想打印它。
在 Unix 世界中,我认为这会涉及转义码,我不确定 Windows 世界,但这对我来说也很重要。
我知道没有颜色怎么做:
fn exec_git() -> String {
let output = Command::new("git")
.arg("status")
.output()
.expect("failed to execute process");
String::from_utf8_lossy(&output.stdout).into_owned()
}
也许我应该改用 spawn
?
您可以使用git -c color.status=always status
use std::process::Command;
fn main() {
let output = Command::new("git")
.arg("-c")
.arg("color.status=always")
.arg("status")
.output()
.expect("failed to execute process");
let output = String::from_utf8_lossy(&output.stdout).into_owned();
println!("{}", output);
}
这仅适用于 git status
。对于更通用的解决方案,您要么必须检查程序文档并希望有一种方法可以强制彩色输出,要么检查程序如何确定它是否应该输出颜色(例如检查 COLORTERM
环境变量).
您的代码已经有效:
use std::process::Command;
fn main() {
let output = Command::new("ls")
.args(&["-l", "--color"])
.env("LS_COLORS", "rs=0:di=38;5;27:mh=44;38;5;15")
.output()
.expect("Failed to execute");
let sout = String::from_utf8(output.stdout).expect("Not UTF-8");
let serr = String::from_utf8(output.stderr).expect("Not UTF-8");
println!("{}", sout);
println!("{}", serr);
}
打印输出:
total 68
-rw-r--r-- 4 root root 56158 Dec 23 00:00 [0m[44;38;5;15mCargo.lock[0m
-rw-rw-r-- 4 root root 2093 Dec 9 02:54 [44;38;5;15mCargo.toml[0m
drwxr-xr-x 1 root root 4096 Dec 30 15:24 [38;5;27msrc[0m
drwxr-xr-x 1 root root 4096 Dec 23 00:19 [38;5;27mtarget[0m
请注意,输出中散布着一堆垃圾([44;
、[0m
等)。这些是 ANSI escape codes,终端仿真器解释这些以更改以下文本的颜色。
如果你打印带调试的字符串,你会看到:
\u{1b}[0m\u{1b}[44;38;5;15mCargo.lock\u{1b}[0m
每个转义码都以 ESC
(\u{1b}
) 开头,后跟实际命令。您将不得不解析它们,以便在您进行的任何处理中忽略它们。
Windows 不使用转义码(尽管 maybe it can in Windows 10?), and instead a program directly modifies the console it is connected to。输出中没有任何内容指示颜色。