如何捕获通过管道传输到 Rust 程序的进程的输出?
How to capture the output of a process piped into a Rust program?
我知道如何读取命令行参数,但我在读取管道的命令输出时遇到困难。
连接程序 (A),使用管道将数据输出到我的 Rust 程序:
A | R
程序应逐行处理数据。
$ pwd | cargo run
应该打印 pwd
输出。
或
$ find . | cargo run
应该输出超过 1 行的 find
命令输出。
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
您只需要阅读 Stdin
。
这基于取自 the documentation 的示例:
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;
}
}
}
}
主要是把docs示例包裹在一个循环中,在没有更多输入或出现错误时跳出循环。
另一个变化是在您的上下文中将错误写入 stderr
更好,这就是错误分支使用 eprintln!
而不是 println!
的原因。编写该文档时,此宏可能不可用。
使用BufRead::lines
on a locked handle to standard input:
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();
}
}
我知道如何读取命令行参数,但我在读取管道的命令输出时遇到困难。
连接程序 (A),使用管道将数据输出到我的 Rust 程序:
A | R
程序应逐行处理数据。
$ pwd | cargo run
应该打印pwd
输出。或
$ find . | cargo run
应该输出超过 1 行的find
命令输出。
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
您只需要阅读 Stdin
。
这基于取自 the documentation 的示例:
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;
}
}
}
}
主要是把docs示例包裹在一个循环中,在没有更多输入或出现错误时跳出循环。
另一个变化是在您的上下文中将错误写入 stderr
更好,这就是错误分支使用 eprintln!
而不是 println!
的原因。编写该文档时,此宏可能不可用。
使用BufRead::lines
on a locked handle to standard input:
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();
}
}