学习Rust的第29天: cat in Rust

今天即将是这个系列的最后一次内容,我们正在catRust 中从 GNU 核心实用程序进行重建。cat用于将文件内容打印到STDOUT.听起来很容易构建,所以让我们开始吧。

GitHub 存储库:GitHub - shafinmurani/gnu-core-utils-rust

伪代码

ba 复制代码
function read(path)->result{
  read contents of path
  propogate any errors to the caller
}

args = command_line_arguments
remove the first element of the args vector

if args.length == 0 {
  print error_message
}
else if args.contains("--help") {
  print help_message
} else {
  for path in args {
    result = remove(path);
    error handling
  }
}

设置任务

正如我们往常所做的那样,让我们impl在库箱中创建一个结构体和一个块。

ba 复制代码
pub struct Config<'a> {
  file_names: &'a Vec<String>,
}

impl Config<'_> {
  pub fn new(args: &Vec<String>){
    Config{ file_names: args }
  }

  fn not_enough_arguments(){
    eprintln!("cat: missing operand");
    eprintln!("for help: cat --help");
  }

  fn help(){
    eprintln!("Welcome to cat in Rust, This is a a little copy of the cat utility present in the GNU core utilities. I made this to practice my rust skills. Check out my articles at https://shafinmurani.medium.com");
    eprintln!("To use: cat file_name1 file_name2 file_name3");
  }

  fn read_documents(){}

  pub fn run(&self){
    if self.file_names.len() == 0 {
      Self::not_enough_arguments();
    } else if self.file_names.contain(&String::from("--help")){
      Self::help();
    } else {
      //We call the read_documents function here
    }
  }
}
  • 该代码定义了一个Config带有生命周期参数的结构体'a,其中包含一个file_names对字符串向量的引用的字段。
  • Config结构有一个关联的实现块 ( impl),用于与 相关的方法Config
  • new方法是 的构造函数Config,将对字符串向量的引用args作为输入,并返回一个设置为 的Config实例。file_names``args
  • not_enough_arguments方法向 stderr 打印一条错误消息,指示该cat命令缺少操作数,建议使用cat --help.
  • help方法打印欢迎消息和cat命令的使用说明。
  • read_documents方法当前留空,可能会被实现来读取和打印指定文件的内容。
  • run方法是执行命令的主要函数cat
  • 它首先检查是否没有提供文件名,在这种情况下它调用not_enough_arguments.
  • 然后它检查--help文件名中是否存在该标志,如果存在,则调用该help方法。
  • 否则,假设提供了文件名,并且它将继续读取和打印这些文件的内容,当前将其作为注释保留。

read_documents() 方法

我们将向此函数传递一个文件路径,它将输出文件的内容,为此,我们使用以下内容:

  1. std::fs::File: 打开文件
  2. std::io::Read:将内容读取到字符串变量

让我们导入这些东西并编写read_document()函数并使用它

ba 复制代码
use std::fs::File;
use std::io::Read;

pub struct Config<'a> {
  file_names: &'a Vec<String>,
}

impl Config<'_> {
  pub fn new(args: &Vec<String>){
    Config{ file_names: args }
  }

  fn not_enough_arguments(){
    eprintln!("cat: missing operand");
    eprintln!("for help: cat --help");
  }

  fn help(){
    eprintln!("Welcome to cat in Rust, This is a a little copy of the cat utility present in the GNU core utilities. I made this to practice my rust skills. Check out my articles at https://shafinmurani.medium.com");
    eprintln!("To use: cat file_name1 file_name2 file_name3");
  }

  fn read_documents(file: String) -> std::io::Result<String>{
    let mut file_buffer = File::open(file)?;
    let mut file_content = String::new();

    file_buffer.read_to_string(&mut file_content)?;
    Ok(file_content)
  }

  pub fn run(&self){
    if self.file_names.len() == 0 {
      Self::not_enough_arguments();
    } else if self.file_names.contain(&String::from("--help")){
      Self::help();
    } else {
      for file in self.file_names {
        let result = Self::read_document(file.to_string());
        match result {
          Ok(data) => println!("{}",data),
          Err(e) => eprintln!("Application Error: `{}` {}", file, e),
        };
      }
    }
  }
}

现在这一切都完成了,我们可以处理我们的二进制箱并专注于运行它......

二进制箱

这里的逻辑很简单

  1. 导入Config结构体
  2. 获取命令行参数
  3. 删除第一个参数
  4. 实例化配置
  5. 配置.run()

让我们实践并运行它。

ba 复制代码
use cat::Config;
use std::env;

fn main(){
  let mut args: Vec<String> = env::args().collect();
  args.remove(0);
  
  let config = Config::new(args);
  config.run();
}

运行它

cat我们将使用该工具来阅读我们工具的源代码cat。谈论 Catception 💀

ba 复制代码
# ./cat lib.rs

use std::fs::File;
use std::io::Read;

pub struct Config<'a>{
    file_names: &'a Vec<String>,
}

impl Config<'_>{
    pub fn new(args: &Vec<String>) -> Config{
        Config{ file_names: args }
    }

    fn help(){
        eprintln!("Welcome to cat in Rust, This is a little copy of the cat utility present in the GNU core utilities. I made this to practice my rust skills. Check out my articles at https://shafinmurani.medium.com");
        eprintln!("To use: cat file_name1 file_name2 ... file_nameN");
    }

    fn not_enough_arguments(){
        eprintln!("cat: missing operand");
        eprintln!("for help: cat --help");
    }

    fn read_document(file: String) -> std::io::Result<String>{
        let mut file_buffer = File::open(file)?;
        let mut file_content = String::new();

        file_buffer.read_to_string(&mut file_content)?;
        Ok(file_content)
    }

    pub fn run(&self){
        if self.file_names.len() == 0 {
            Self::not_enough_arguments();
        } else if self.file_names.contains(&String::from("--help")) {
            Self::help();
        } else {
            for file in self.file_names {
               let result = Self::read_document(file.to_string());
                match result {
                    Ok(r) => println!("{}",r),
                    Err(e) => eprintln!("Application Error: `{}` {}",file,e)
                };
            }
        }
    }
}

结论

库文件

  • lib.rs文件定义了 crate 的主要功能cat
  • 它从标准库(std::fs::Filestd::io::Read)导入必要的模块以进行文件处理。
  • 它声明了一个Config带有生命周期参数的结构体'a,其中包含一个file_names对字符串向量的引用的字段。
  • impl与 相关的方法有一个实现块 ( ) Config
  • new方法是 的构造函数Config,将对字符串向量的引用args作为输入,并返回一个设置为 的Config实例。file_names``args
  • help方法打印欢迎消息和cat命令的使用说明。
  • not_enough_arguments方法向 stderr 打印一条错误消息,指示该cat命令缺少操作数,建议使用cat --help.
  • read_document方法读取由名称指定的文件的内容并将其作为 a 返回String,处理潜在的 IO 错误。
  • run方法是执行命令的主要函数cat
  • 它检查是否没有提供文件名,在这种情况下它调用not_enough_arguments.
  • 然后它检查--help文件名中是否存在该标志,如果存在,则调用该help方法。
  • 否则,它会迭代每个文件名,使用 读取其内容read_document,并将其打印到标准输出。

主程序.rs

  • main.rs文件充当可执行文件的入口点。
  • 它从板条箱Config中导入结构catenv从标准库中导入模块。
  • main函数将命令行参数收集到字符串向量中,删除第一个参数(程序名称本身),然后Config使用剩余参数创建一个实例Config::new
  • 最后,它调用实例run上的方法Config来执行cat命令。
相关推荐
红尘散仙9 小时前
我把终端小说阅读器接上了 AI Agent:TRNovel 现在能用 skill 生成书源了
人工智能·后端·rust
卷毛的技术笔记11 小时前
告别硬编码!Spring AI Alibaba 实现 AI Agent 智能工具调用(Tool Calling)
java·人工智能·后端·python·spring·ai编程
isyangli_blog11 小时前
OpenDayLight (Carbon 版本) 启动与组件安装
开发语言·php
vb20081111 小时前
FastAPI APIRouter
开发语言·python
Benszen11 小时前
KVM虚拟化解决方案
开发语言·perl
会编程的土豆11 小时前
Go 语言反射(Reflection)详解
开发语言·后端·golang
東雪木11 小时前
多线程与并发编程 专属复习笔记
java·开发语言·笔记·java面试
喵个咪11 小时前
GoWind Toolkit Go后端代码生成 完整全流程实战
后端·go·orm
杨充11 小时前
1.3 浮点型数据设计灵魂
开发语言·python·算法
噜噜噜阿鲁~11 小时前
python学习笔记 | 11.3、面向对象高级编程-多重继承
java·开发语言