Rust练手项目1--minigrep

minigrep

官方教程断断续续看了10章,写个小demo练习下。目前感觉还行,继续看完再来重构一个版本。

目录结构

cargo.toml

toml 复制代码
[package]
name = "minigrep"
version = "0.0.1"
edition = "2024"

[dependencies]

grepp.txt

txt 复制代码
I'm nobody! Who are you?
Are you nobody, too?
Then there's a pair of us - don't tell!
They'd banish us, you know.

How dreary to be somebody!
How public, like a frog
To tell your name the livelong day
To an admiring bog!

main.rs

rust 复制代码
use std::env::args;

fn main() {
    let args: Vec<String> = args().collect();
    // 去掉第一个参数
    let params = &args[1..].to_vec();
    minigrep::grep(params);
}

lib.rs

rust 复制代码
use std::io::{Error};
use std::io::ErrorKind::InvalidInput;
use std::process;
use crate::common::status::Status;
pub mod common;

pub fn grep(params:&Vec<String>){
    check_params(&params);
    use common::content::Content;
    let result =  Content::parse(&params).search();
    if !result.is_empty(){
        println!("{:?}", result);
    }
}

/// 校验参数
fn check_params(params:&Vec<String>){
    // 检验长度
    let mut  status = check_params_len(params.len()).unwrap_or_else(out_err);
    if status.eq(&Status::Stop){
        process::exit(0);
    }
    // 检验合法
    status = check_params_invalid(params).unwrap_or_else(out_err);
    if status.eq(&Status::Stop){
        process::exit(0);
    }
}
fn check_params_len(len:usize) -> Result<Status,Error>{
    if len > 0 {
        return Ok(Status::Continue )
    }
    Err(Error::new(InvalidInput,"未指定有效参数 --help 可查看支持的参数!"))
}

fn check_params_invalid(params:&Vec<String>) -> Result<Status, Error>{
    use common::commands::Commands;
    let commands = Commands::values();
    for param in params {
        for command in &commands {
         if param.to_lowercase().starts_with(command.as_str()) {
             let display = command.display();
             if display.is_empty() {
                 return Ok(Status::Continue)
             }else {
                 println!("{}", display);
                 return Ok(Status::Stop )
             }
            }
        }
    }
    Ok(Status::Continue)
}

fn out_err(error:Error) -> Status{
    eprintln!("参数错误:{}", error);
    process::exit(1);
}

common/mod.rs

rust 复制代码
pub mod content;
pub mod commands;
pub mod status;

common/commands.rs

rust 复制代码
pub enum Commands {
    Help,
    Version,
    FilePath,
    LowerCase,
    Keyword,
}
impl Commands {
    pub fn as_str(&self) -> &str {
        use Commands::*;
        match *self {
            Help => "--help",
            Version => "--version",
            FilePath => "--filepath",
            LowerCase => "--lowercase",
            Keyword => "--keyword",
        }
    }
    pub fn values() -> Vec<Commands> {
        use Commands::*;
        vec![Help, Version, FilePath, LowerCase, Keyword]
    }

    pub fn display(&self) -> &str{
        use Commands::*;
        match *self {
            Help => "--help \t 帮助 \n \
            --version \t 版本 \n \
            --filepath=xxx.txt \t 文件路径 \n \
            --lowercase=false \t 是否忽略大小写 \n \
            --keyword=key \t 搜索关键词 \n",
            Version => "0.0.1",
            _ => "",
        }
    }
}

common/content.rs

rust 复制代码
use std::{fs, process};

pub struct Content{
    file_path: String, // 文件路径
    search_keyword:String, //搜索关键字
    context: String, // 文件内容
    lowercase:bool,//忽略大小写
}

impl Content {
   pub fn parse(params:&Vec<String>)->Content{
       let mut content = Content {
           file_path: "".to_string(),
           search_keyword: "".to_string(),
           context: "".to_string(),
           lowercase: true
       };
       for param in params {
           if param.to_lowercase().starts_with("--filepath="){
               content.file_path = param.replace("--filepath=", "");
           }
           if param.to_lowercase().starts_with("--keyword="){
               content.search_keyword = param.replace("--keyword=", "");
           }
           if param.to_lowercase().starts_with("--lowercase="){
               content.lowercase = param.replace("--lowercase=", "").parse().unwrap_or_default();
           }
       }
       if content.search_keyword.is_empty() {
           eprintln!("No search keyword specified");
           process::exit(1);
       }
       if !content.file_path.is_empty() {
           let result = fs::read_to_string(&content.file_path)
               .unwrap_or_else(|err| {
                   eprintln!("Error reading file: {}", err);
                   process::exit(1)
               });
           content.context = result.trim().to_string();
       }
       if content.context.is_empty() {
           eprintln!("No context specified");
           process::exit(1);
       }
       content
    }

    pub fn search(&self) -> Vec<String> {
        let mut resut = vec![];
        if self.context.is_empty() {
            vec![]
        }else {
            let mut key = self.search_keyword.clone();
            for line in self.context.lines() {
                if !line.is_empty() {
                    let mut context = line.to_string();
                    if self.lowercase{
                        context = line.to_string().to_lowercase();
                        key = key.to_lowercase();
                    }
                    if context.contains(&key) {
                        resut.push(context);
                    }
                }
            }
            resut
        }
    }
}

common/status.rs

rust 复制代码
#[derive(PartialEq)]
pub enum Status{
    Stop,
    Continue,
}

输出

相关推荐
Hi2024021717 分钟前
同一个 NMS 算子,两种语言实现:CUDA C 与 Rust 生成 LLVM IR 和 Vortex 汇编的差异
c语言·汇编·rust·gpgpu·vortex·cudac
滕州市燕猫虎计算机科技工作室个体工商户26 分钟前
《Rust程序设计》学习笔记一
开发语言·rust·学习笔记·rust程序设计
小道士写程序4 小时前
Windows Rust 环境安装指导
开发语言·windows·rust
leikooo2 天前
用餐厅和盘子理解栈和堆
java·数据结构·链表·rust
@大迁世界2 天前
JEV RAG:更高效的 RAG 系统解决方案?
开发语言·rust
进击的雷神2 天前
OpenClaw 太重、启动太慢?我试了试这个 Rust 重写的轻量版 AI 助手网关
开发语言·人工智能·rust·zeroclaw
选择即世界2 天前
高性能的 SGLang Rust 运行时
rust