如何捕获通过管道传输到 Rust 程序的进程的输出?

问题描述 投票:0回答:5

我知道如何读取命令行参数,但我在读取管道的命令输出时遇到困难。

  1. 使用管道连接一个将数据输出到我的 Rust 程序的程序 (A):

    A | R
    
  2. 程序应该逐行消耗数据。

    $ pwd | cargo run
    应打印
    pwd
    输出。

    $ find . | cargo run
    应输出超过 1 行的
    find
    命令输出。

rust pipe rust-cargo
5个回答
19
投票

在标准输入的锁定句柄上使用

BufRead::lines:

use std::io::{self, BufRead};

fn main() {
    let stdin = io::stdin();
    for line in stdin.lock().lines() {
        let line = line.expect("Could not read line from standard in");
        println!("{}", line);
    }
}

如果你想重用

String
的分配,你可以使用循环形式:

use std::io::{self, Read};

fn main() {
    let stdin = io::stdin();
    let mut stdin = stdin.lock(); // locking is optional

    let mut line = String::new();

    // Could also `match` on the `Result` if you wanted to handle `Err` 
    while let Ok(n_bytes) = stdin.read_to_string(&mut line) {
        if n_bytes == 0 { break }
        println!("{}", line);
        line.clear();
    }
}

7
投票

您只需阅读

Stdin

这是基于来自文档的示例:

use std::io;

fn main() {
    loop {
        let mut input = String::new();
        match io::stdin().read_line(&mut input) {
            Ok(len) => if len == 0 {
                return;
            } else {
                println!("{}", input);
            } 
            Err(error) => {
                eprintln!("error: {}", error);
                return;
            }
        }
    }
}

它主要是包裹在循环中的文档示例,当没有更多输入或出现错误时,会跳出循环。

其他更改是,在您的上下文中最好将错误写入

stderr
,这就是错误分支使用
eprintln!
而不是
println!
的原因。该宏在编写该文档时可能不可用。


2
投票
use std::io;

fn main() {
    loop {
        let mut input = String::new();
        io::stdin()
            .read_line(&mut input)
            .expect("failed to read from pipe");
        input = input.trim().to_string();
        if input == "" {
            break;
        }
        println!("Pipe output: {}", input);
    }
}

输出:

[18:50:29 Abhinickz@wsl -> pipe$ pwd
/mnt/d/Abhinickz/dev_work/learn_rust/pipe
[18:50:46 Abhinickz@wsl -> pipe$ pwd | cargo run
    Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs
    Running `target/debug/pipe`
Pipe output: /mnt/d/Abhinickz/dev_work/learn_rust/pipe

2
投票

你可以使用 Rust 的迭代器方法以一种非常时髦和简洁的方式来完成它

use std::io::{self, BufRead};

fn main() {

    // get piped input
    //   eg `cat file | ./program`
    //    ( `cat file | cargo run` also works )

    let input = io::stdin().lock().lines().fold("".to_string(), |acc, line| {
        acc + &line.unwrap() + "\n"
    });

    dbg!(input);

}


0
投票

read_to_string()的结果太简单,请修改。

use std::io::{self, IsTerminal};

fn main() {
    let stdin = io::stdin();
    if !stdin.is_terminal() { // v1.70.0 later
        let text = io::read_to_string(stdin).expect("Can not read stdin");
        println!("{}", text);
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.