支持多文件
如果想实现如下的多文件使用方式,需要再次调整 clap
解析逻辑。
grustep pattern file1.txt file2.txt file3.txt
# Or
grustep pattern *.txt
注意:
在命令行中直接使用*.txt
作为参数可能不会一定按你的预期工作,因为通配符模式(如*.txt
)的展开是由 shell(例如 Bash)展开的。 Rust 中的clap
模块不会自动执行此展开。不过,你可以使用 crateglob
手动展开。
添加多路径版本的 grep
,src/lib.rs:
pub fn grep_multi(
pattern: &str,
file_paths: &Vec<&str>,
options: &GrepOptions,
) -> Result<MatchResult, io::Error> {
if file_paths.is_empty() {
// 用于管道读取,比如 "cat a.txt | ..."
return grep(pattern, Path::new(""), options);
}
let mut results = MatchResult::new();
for &file_path in file_paths {
if let Ok(result) = grep(pattern, Path::new(file_path), options) {
results.extend(result);
}
}
Ok(results)
}
pub fn grep_recursive_multi(
pattern: &str,
dir_paths: &Vec<&str>,
options: &GrepOptions,
) -> Result<MatchResult, io::Error> {
let mut results = MatchResult::new();
for &dir_path in dir_paths {
if let Ok(result) = grep_recursive(pattern, Path::new(dir_path), options) {
results.extend(result);
}
}
Ok(results)
}
修改 clap
部分,并调用多路径版本函数,main.rs:
@@ -1,5 +1,6 @@
use clap::{App, Arg};
-use lr_grustep::{grep, grep_count, grep_recursive, GrepOptions, MatchResult};
+
+use lr_grustep::{grep_count, grep_multi, grep_recursive_multi, GrepOptions, MatchResult};
fn main() {
// Define command-line arguments using clap
@@ -8,7 +9,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(false).index(2).help("The file to search in"))
+ .arg(Arg::with_name("file_paths").required(false).multiple(true).help("The files 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,16 +19,19 @@ fn main() {
// Extract command-line arguments
let pattern = matches.value_of("pattern").unwrap();
- let file_path = matches.value_of("file_path").unwrap_or("");
+ let file_paths: Vec<&str> = matches
+ .values_of("file_paths")
+ .unwrap_or_default()
+ .collect();
let options = GrepOptions {
ignore_case: matches.is_present("ignore-case"),
invert_match: matches.is_present("invert-match"),
};
- let result = if matches.is_present("recursive") && !file_path.is_empty() {
- grep_recursive(pattern, file_path.as_ref(), &options)
+ let result = if matches.is_present("recursive") && !file_paths.is_empty() {
+ grep_recursive_multi(pattern, &file_paths, &options)
} else {
- grep(pattern, file_path.as_ref(), &options)
+ grep_multi(pattern, &file_paths, &options)
};
重新安装你的项目:
cargo install --path .
# 或者
make install
然后即可执行如下操作:
grustep -n result src/*rs
# 或者
grustep -n result src/lib.rs src/main.rs
结果:
src/lib.rs:
42: let mut result = MatchResult::new();
43: result.insert(file_path.to_string_lossy().to_string(), matching_lines);
44: Ok(result)
56: let mut results = MatchResult::new();
58: if let Ok(result) = grep(pattern, Path::new(file_path), options) {
59: results.extend(result);
62: Ok(results)
65: pub fn grep_count(result: &MatchResult) -> usize {
66: result.values().map(|v| v.len()).sum()
74: let mut results = MatchResult::new();
79: let result = grep(pattern, file_path, options)?;
80: results.extend(result);
83: Ok(results)
91: let mut results = MatchResult::new();
93: if let Ok(result) = grep_recursive(pattern, Path::new(dir_path), options) {
94: results.extend(result);
97: Ok(results)
src/main.rs:
31: let result = if matches.is_present("recursive") && !file_paths.is_empty() {
37: match result {
38: Ok(result) => {
40: println!("{}", grep_count(&result));
42: print_result(&result, matches.is_present("line-number"))
51: fn print_result(result: &MatchResult, show_line_number: bool) {
53: let file_count = result.len();
55: for (file_path, items) in result {
恭喜🎉!你已经用 Rust 创建了一个很赞的命令行程序。
项目完整代码:https://github.com/Literank/lr_grustep
持续前进!持续学习!