支持管道
在类 Unix 操作系统(如 Linux 和 macOS)中,管道是一种用于进程间通信(IPC)的机制,允许一个进程的输出被用作另一个进程的输入。
在 Shell 命令中,管道由 |
符号表示。当你使用类似 command1 | command2
的命令时,意味着 command1
的标准输出被连接到 command2
的标准输入。
例如:
cat file.txt | grep "pattern"
在此命令中,file.txt
的内容被作为输入传递到 grep
命令,该命令搜索指定的模式。
修改 src/main.rs 以使 file_path
参数可选:
@@ -8,7 +8,7 @@ fn main() {
.author("literank")
.about("A grep-like utility in Rust")
.arg(Arg::with_name("pattern").required(true).index(1).help("The pattern to search for"))
- .arg(Arg::with_name("file_path").required(true).index(2).help("The file to search in"))
+ .arg(Arg::with_name("file_path").required(false).index(2).help("The file to search in"))
.arg(Arg::with_name("count").short("c").long("count").help("Only a count of selected lines is written to standard output"))
.arg(Arg::with_name("ignore-case").short("i").long("ignore-case").help("Perform case-insensitive matching"))
.arg(Arg::with_name("line-number").short("n").long("line-number").help("Each output line is preceded by its relative line number in the file, starting at line 1"))
@@ -18,13 +18,13 @@ fn main() {
// Extract command-line arguments
let pattern = matches.value_of("pattern").unwrap();
- let file_path = matches.value_of("file_path").unwrap();
+ let file_path = matches.value_of("file_path").unwrap_or("");
let options = GrepOptions {
ignore_case: matches.is_present("ignore-case"),
invert_match: matches.is_present("invert-match"),
};
文件路径为空时无法做递归搜索,故修改 src/main.rs:
- let result = if matches.is_present("recursive") {
+ let result = if matches.is_present("recursive") && !file_path.is_empty() {
grep_recursive(pattern, file_path.as_ref(), &options)
} else {
grep(pattern, file_path.as_ref(), &options)
在 src/lib.rs 中,当 file_path
为空时,从标准输入读取内容:
@@ -66,8 +66,12 @@ pub fn grep_recursive(
}
fn read_file_lines(file_path: &Path) -> Result<Vec<String>, io::Error> {
- let file = fs::File::open(file_path)?;
- let reader = io::BufReader::new(file);
+ let reader: Box<dyn BufRead> = if file_path.components().count() == 0 {
+ Box::new(io::BufReader::new(io::stdin()))
+ } else {
+ let file = fs::File::open(file_path)?;
+ Box::new(io::BufReader::new(file))
+ };
Ok(reader.lines().map_while(Result::ok).collect())
}
现在可以执行以下操作:
cat src/main.rs | cargo run -- -n line
其结果:
5: // Define command-line arguments using clap
12: .arg(Arg::with_name("count").short("c").long("count").help("Only a count of selected lines is written to standard output"))
14: .arg(Arg::with_name("line-number").short("n").long("line-number").help("Each output line is preceded by its relative line number in the file, starting at line 1"))
16: .arg(Arg::with_name("invert-match").short("v").long("invert-match").help("Selected lines are those not matching any of the specified patterns"))
19: // Extract command-line arguments
38: print_result(&result, matches.is_present("line-number"))
47: fn print_result(result: &MatchResult, show_line_number: bool) {
57: if show_line_number {
58: println!("{}: {}", item.line_number, item.line);
60: println!("{}", item.line);
重新安装后,你的 grustep
也可以支持管道。
cat src/main.rs | grustep -n line
其结果与上面相同。