Skip to content

Commit fd60d45

Browse files
committed
提交命令管道实验
1 parent caa6947 commit fd60d45

File tree

1 file changed

+69
-27
lines changed
  • exercises/01_concurrency_sync/04_process_pipe/src

1 file changed

+69
-27
lines changed

exercises/01_concurrency_sync/04_process_pipe/src/lib.rs

Lines changed: 69 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,16 @@ use std::process::{Command, Stdio};
4949
/// 3. Call `.output()` to execute the child and obtain its `Output`.
5050
/// 4. Convert the `stdout` field (a `Vec<u8>`) into a `String`.
5151
pub fn run_command(program: &str, args: &[&str]) -> String {
52-
// TODO: Use Command::new to create process
53-
// TODO: Set stdout to Stdio::piped()
54-
// TODO: Execute with .output() and get output
55-
// TODO: Convert stdout to String and return
56-
todo!()
52+
// Use Command::new to create process
53+
// Set stdout to Stdio::piped()
54+
// Execute with .output() and get output
55+
let cmd = Command::new(program).args(args).output().unwrap();
56+
if !cmd.status.success() {
57+
// Convert stdout to String and return
58+
String::from_utf8_lossy(&cmd.stderr).to_string()
59+
}else {
60+
String::from_utf8_lossy(&cmd.stdout).to_string()
61+
}
5762
}
5863

5964
/// Write data to child process (cat) stdin via pipe and read its stdout output.
@@ -84,12 +89,19 @@ pub fn run_command(program: &str, args: &[&str]) -> String {
8489
/// 5. Read the child's stdout (`child.stdout.take().unwrap().read_to_string(...)`).
8590
/// 6. Wait for the child to exit with `.wait()` (or rely on drop‑wait).
8691
pub fn pipe_through_cat(input: &str) -> String {
87-
// TODO: Create "cat" command, set stdin and stdout to piped
88-
// TODO: Spawn process
89-
// TODO: Write input to child process stdin
90-
// TODO: Drop stdin to close pipe (otherwise cat won't exit)
91-
// TODO: Read output from child process stdout
92-
todo!()
92+
// Create "cat" command, set stdin and stdout to piped
93+
// 创建 cat 命令,并将标准输入(stdin)和标准输出(stdout)设置为管道模式
94+
// Spawn process 启动(创建)子进程
95+
// Write input to child process stdin 将输入数据写入子进程的标准输入(stdin)
96+
// Drop stdin to close pipe (otherwise cat won't exit) 释放(drop)stdin 以关闭管道(否则 cat 不会退出)
97+
// Read output from child process stdout 从子进程的标准输出(stdout)读取输出数据
98+
let mut child = Command::new("cat").stdin(Stdio::piped()).stdout(Stdio::piped()).spawn().unwrap();
99+
let mut stdin = child.stdin.unwrap();
100+
stdin.write_all(input.as_bytes()).unwrap();
101+
drop(stdin);
102+
let mut buffer = String::new();
103+
child.stdout.take().unwrap().read_to_string(&mut buffer).unwrap();
104+
buffer
93105
}
94106

95107
/// Get child process exit code.
@@ -107,10 +119,11 @@ pub fn pipe_through_cat(input: &str) -> String {
107119
/// 3. Use `.code()` to get the exit code as `Option<i32>`.
108120
/// 4. If the child terminated normally, return the exit code; otherwise return a default.
109121
pub fn get_exit_code(command: &str) -> i32 {
110-
// TODO: Use Command::new("sh").args(["-c", command])
111-
// TODO: Execute and get status
112-
// TODO: Return exit code
113-
todo!()
122+
// Use Command::new("sh").args(["-c", command])
123+
// Execute and get status
124+
let status = Command::new("sh").args(["-c", command]).status().unwrap();
125+
// Return exit code
126+
status.code().unwrap()
114127
}
115128

116129
/// Execute the given shell command and return its stdout output as a `Result`.
@@ -133,11 +146,19 @@ pub fn get_exit_code(command: &str) -> i32 {
133146
/// 3. Call `.output()` and propagate any `io::Error`.
134147
/// 4. Convert `stdout` to `String` with `String::from_utf8`; if that fails, map to an `io::Error`.
135148
pub fn run_command_with_result(program: &str, args: &[&str]) -> io::Result<String> {
136-
// TODO: Use Command::new to create process
137-
// TODO: Set stdout to Stdio::piped()
138-
// TODO: Execute with .output() and handle Result
139-
// TODO: Convert stdout to String with from_utf8, mapping errors to io::Error
140-
todo!()
149+
// Use Command::new to create process
150+
// Set stdout to Stdio::piped()
151+
// Execute with .output() and handle Result
152+
// Convert stdout to String with from_utf8, mapping errors to io::Error
153+
let result = Command::new(program).args(args).stdout(Stdio::piped()).output();
154+
if result.is_ok() {
155+
let output = result.unwrap();
156+
let stdout = String::from_utf8_lossy(&output.stdout);
157+
Ok(stdout.to_string())
158+
}else {
159+
Err(result.unwrap_err())
160+
}
161+
141162
}
142163

143164
/// Interact with `grep` via bidirectional pipes, filtering lines that contain a pattern.
@@ -161,13 +182,34 @@ pub fn run_command_with_result(program: &str, args: &[&str]) -> io::Result<Strin
161182
/// 7. Return the concatenated matching lines as a single `String`.
162183
///
163184
pub fn pipe_through_grep(pattern: &str, input: &str) -> String {
164-
// TODO: Create "grep" command with pattern, set stdin and stdout to piped
165-
// TODO: Spawn process
166-
// TODO: Write input lines to child stdin
167-
// TODO: Drop stdin to close pipe
168-
// TODO: Read output from child stdout line by line
169-
// TODO: Collect and return matching lines
170-
todo!()
185+
// Create "grep" command with pattern, set stdin and stdout to piped
186+
// Spawn process
187+
// Write input lines to child stdin
188+
// Drop stdin to close pipe
189+
// Read output from child stdout line by line
190+
// Collect and return matching lines
191+
let mut child = Command::new("grep")
192+
.arg(pattern)
193+
.stdin(Stdio::piped())
194+
.stdout(Stdio::piped())
195+
.spawn()
196+
.unwrap();
197+
198+
let mut stdin = child.stdin.take().unwrap();
199+
stdin.write_all(input.as_bytes()).unwrap();
200+
drop(stdin);
201+
202+
let mut output = String::new();
203+
child
204+
.stdout
205+
.take()
206+
.unwrap()
207+
.read_to_string(&mut output)
208+
.unwrap();
209+
210+
child.wait().unwrap();
211+
212+
output
171213
}
172214

173215
#[cfg(test)]

0 commit comments

Comments
 (0)