警告
本文最后更新于 2022-04-11 ,文中内容可能已过时。
一个用 Rust 实现的简单的 grep,可以读取文件,匹配正则表达式。
代码思路: 使用 regex 正则表达式库,env 读取 args 命令行参数。第1个参数为文件,第2个参数为正则表达式。
将正则表达式匹配到的行输出,并高亮匹配到的内容。同时显示所在行数。
如果没有第二个正则表达式参数,直接输出文件内容。
最后显示找的几行,几个符合正则表达式的字符串。
Cargo.toml
1
2
3
4
5
6
7
8
9
[ package ]
name = "mygrep"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[ dependencies ]
regex = "1.5.5"
src/main.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
use regex ::Regex ;
use std ::env ;
use std ::fs ::File ;
use std ::io ::Read ;
fn main () {
// ["D:\\rustcode\\grep\\target\\debug\\grep.exe", "1", "2", "3"]
let args : Vec < String > = env ::args (). collect ();
let file_path = args . get ( 1 );
let regex = args . get ( 2 );
let ex = args . get ( 3 );
if ex . is_some () {
red ( "Extra words will be ingroned!" );
}
match file_path {
Some ( path ) => read_file ( path , regex ),
None => {
red ( "No file path provided" );
green ( "Helper: \n mygrep <file_path> <regex>" );
}
}
}
fn read_file ( file_path : & str , regex : Option <& String > ) {
let file = File ::open ( file_path );
match file {
Ok ( mut file ) => {
green ( & format! ( "Reading {} " , file_path ));
let mut contents = String ::new ();
let mut sum_lines = 0 ;
let mut sum_key = 0 ;
file . read_to_string ( & mut contents ). unwrap ();
match regex {
Some ( regex ) => {
let re = Regex ::new ( & regex . to_string ()). unwrap ();
let mut lines = contents . lines ();
let mut k = 1 ;
while let Some ( line ) = lines . next () {
if re . is_match ( line ) {
let mut ans = line . to_string ();
for caps in re . captures_iter ( line ) {
let from = caps . get ( 0 ). unwrap (). as_str ();
ans = ans . replace ( from . clone (), & blue ( from ));
sum_key += 1 ;
// println!("CAPS: {:?}", caps.get(0).unwrap().as_str());
}
sum_lines += 1 ;
println! ( " {} : {} " , yellow ( & k . to_string ()), ans );
}
k += 1 ;
}
}
None => {
let mut k = 1 ;
// println!("{}", contents);
contents . lines (). for_each ( | line | {
println! ( " {} : {} " , yellow ( & k . to_string ()), line );
k += 1 ;
});
}
}
green ( & format! ( "Found {} lines, Key nums: {} " , sum_lines , sum_key ));
}
Err ( e ) => panic! ( "File Open Error: {} " , e ),
}
// println!("read {:?}", file_path);
}
fn red ( msg : & str ) {
println! ( " \x1b [91m {} \x1b [0m" , msg );
}
fn green ( msg : & str ) {
println! ( " \x1b [92m {} \x1b [0m" , msg );
}
fn yellow ( msg : & str ) -> String {
format! ( " \x1b [93m {} \x1b [0m" , msg )
}
fn blue ( msg : & str ) -> String {
format! ( " \x1b [94m {} \x1b [0m" , msg )
}
没有进行单元测试,异常也是直接抛出。对这个程序影响不是很大。
test.txt
1
2
3
4
read
bluetooth
blur old false
bluetooth bluetooth bluetoothbluetooth
text.txt测试 将 grep 路径加入操作系统的环境变量,然后就可以在终端中正常使用了。下面测试正则表达式的支持情况。
测试文件: https://www.ftls.xyz/posts/eshaas/index.md 结果:
正则表达式匹配和显示