在 Rust 中,如何用颜色捕获过程输出?

Woj*_*lak 6 terminal console tty windows-console rust

我想捕获另一个进程的输出(例如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()
}
Run Code Online (Sandbox Code Playgroud)

也许我应该改用spawn

She*_*ter 2

您的代码已经可以运行

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);
}
Run Code Online (Sandbox Code Playgroud)

打印输出:

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);
}
Run Code Online (Sandbox Code Playgroud)

请注意,输出中散布着一堆垃圾([44;[0m等)。这些是ANSI 转义码,终端仿真器解释这些代码以更改以下文本的颜色。

如果通过调试打印字符串,您将看到:

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
Run Code Online (Sandbox Code Playgroud)

每个转义码都以ESC( \u{1b}) 开头,后跟实际命令。您必须解析它们,以便在您正在进行的任何处理中忽略它们。

Windows 不使用转义码(尽管在 Windows 10 中也许可以?),而是由程序直接修改它所连接的控制台。输出中没有任何内容来指示颜色。