Accepting Command Line Arguments

RustRustBeginner
Pratiquer maintenant

This tutorial is from open-source community. Access the source code

💡 Ce tutoriel est traduit par l'IA à partir de la version anglaise. Pour voir la version originale, vous pouvez cliquer ici

Introduction

Bienvenue dans Accepting Command Line Arguments. Ce laboratoire est une partie du Rust Book. Vous pouvez pratiquer vos compétences Rust dans LabEx.

Dans ce laboratoire, nous allons créer un nouveau projet appelé "minigrep" qui accepte deux arguments de ligne de commande : une chaîne de caractères à rechercher et un chemin de fichier.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL rust(("Rust")) -.-> rust/DataStructuresandEnumsGroup(["Data Structures and Enums"]) rust(("Rust")) -.-> rust/AdvancedTopicsGroup(["Advanced Topics"]) rust(("Rust")) -.-> rust/BasicConceptsGroup(["Basic Concepts"]) rust(("Rust")) -.-> rust/FunctionsandClosuresGroup(["Functions and Closures"]) rust/BasicConceptsGroup -.-> rust/variable_declarations("Variable Declarations") rust/FunctionsandClosuresGroup -.-> rust/function_syntax("Function Syntax") rust/FunctionsandClosuresGroup -.-> rust/expressions_statements("Expressions and Statements") rust/DataStructuresandEnumsGroup -.-> rust/method_syntax("Method Syntax") rust/AdvancedTopicsGroup -.-> rust/operator_overloading("Traits for Operator Overloading") subgraph Lab Skills rust/variable_declarations -.-> lab-100418{{"Accepting Command Line Arguments"}} rust/function_syntax -.-> lab-100418{{"Accepting Command Line Arguments"}} rust/expressions_statements -.-> lab-100418{{"Accepting Command Line Arguments"}} rust/method_syntax -.-> lab-100418{{"Accepting Command Line Arguments"}} rust/operator_overloading -.-> lab-100418{{"Accepting Command Line Arguments"}} end

Accepting Command Line Arguments

Créons un nouveau projet avec, comme toujours, cargo new. Nous appellerons notre projet minigrep pour le distinguer de l'outil grep que vous pouvez déjà avoir sur votre système.

$ cargo new minigrep
     Created binary (application) `minigrep` project
$ cd minigrep

La première tâche est de faire en sorte que minigrep accepte ses deux arguments de ligne de commande : le chemin du fichier et une chaîne de caractères à rechercher. C'est-à-dire que nous voulons être en mesure d'exécuter notre programme avec cargo run, deux tirets pour indiquer que les arguments suivants sont pour notre programme et non pour cargo, une chaîne de caractères à rechercher et un chemin vers un fichier dans lequel effectuer la recherche, comme ceci :

cargo run -- searchstring example-filename.txt

En ce moment, le programme généré par cargo new ne peut pas traiter les arguments que nous lui donnons. Certaines bibliothèques existantes sur https://crates.io peuvent aider à écrire un programme qui accepte des arguments de ligne de commande, mais comme vous apprenez juste ce concept, implémentons cette fonctionnalité nous-mêmes.

Reading the Argument Values

Pour permettre à minigrep de lire les valeurs des arguments de ligne de commande que nous lui passons, nous aurons besoin de la fonction std::env::args fournie dans la bibliothèque standard de Rust. Cette fonction renvoie un itérateur des arguments de ligne de commande passés à minigrep. Nous aborderons les itérateurs en détail au chapitre 13. Pour l'instant, vous n'avez besoin de connaître que deux détails sur les itérateurs : les itérateurs produisent une série de valeurs, et nous pouvons appeler la méthode collect sur un itérateur pour le transformer en une collection, telle qu'un vecteur, qui contient tous les éléments produits par l'itérateur.

Le code de la liste 12-1 permet à votre programme minigrep de lire tous les arguments de ligne de commande passés à celui-ci, puis de collecter les valeurs dans un vecteur.

Nom de fichier : src/main.rs

use std::env;

fn main() {
    let args: Vec<String> = env::args().collect();
    dbg!(args);
}

Liste 12-1 : Collecter les arguments de ligne de commande dans un vecteur et les imprimer

Tout d'abord, nous importons le module std::env dans la portée avec une instruction use pour pouvoir utiliser sa fonction args. Remarquez que la fonction std::env::args est imbriquée dans deux niveaux de modules. Comme nous l'avons discuté au chapitre 7, dans les cas où la fonction souhaitée est imbriquée dans plus d'un module, nous avons choisi d'importer le module parent dans la portée plutôt que la fonction. En faisant ainsi, nous pouvons facilement utiliser d'autres fonctions de std::env. Cela est également moins ambigu que d'ajouter use std::env::args puis d'appeler la fonction avec seulement args, car args pourrait facilement être confondu avec une fonction définie dans le module actuel.

La fonction args et l'Unicode invalide

Notez que std::env::args provoquera une panique si un argument contient un Unicode invalide. Si votre programme doit accepter des arguments contenant un Unicode invalide, utilisez std::env::args_os à la place. Cette fonction renvoie un itérateur qui produit des valeurs OsString au lieu de String valeurs. Nous avons choisi d'utiliser std::env::args ici pour la simplicité car les valeurs OsString diffèrent selon la plateforme et sont plus complexes à manipuler que les valeurs String.

Sur la première ligne de main, nous appelons env::args, et nous utilisons immédiatement collect pour transformer l'itérateur en un vecteur contenant toutes les valeurs produites par l'itérateur. Nous pouvons utiliser la fonction collect pour créer de nombreux types de collections, donc nous annotons explicitement le type de args pour spécifier que nous voulons un vecteur de chaînes de caractères. Bien que vous ayez très rarement besoin d'annoter les types en Rust, collect est une fonction pour laquelle vous devez souvent annoter le type car Rust n'est pas capable d'inférer le type de collection que vous voulez.

Enfin, nous imprimons le vecteur à l'aide de la macro de débogage. Essayons d'exécuter le code d'abord sans arguments puis avec deux arguments :

$ cargo run
--snip--
[src/main.rs:5] args = [
"target/debug/minigrep",
]
$ cargo run -- needle haystack
--snip--
[src/main.rs:5] args = [
"target/debug/minigrep",
"needle",
"haystack",
]

Remarquez que la première valeur dans le vecteur est "target/debug/minigrep", qui est le nom de notre binaire. Cela correspond au comportement de la liste d'arguments en C, permettant aux programmes d'utiliser le nom sous lequel ils ont été invoqués dans leur exécution. Il est souvent pratique d'avoir accès au nom du programme au cas où vous voudriez l'imprimer dans des messages ou changer le comportement du programme en fonction de l'alias de ligne de commande utilisé pour invoquer le programme. Mais dans le cadre de ce chapitre, nous allons l'ignorer et ne conserver que les deux arguments dont nous avons besoin.

Saving the Argument Values in Variables

Le programme est actuellement capable d'accéder aux valeurs spécifiées comme arguments de ligne de commande. Maintenant, nous devons enregistrer les valeurs des deux arguments dans des variables pour pouvoir utiliser les valeurs dans le reste du programme. Nous le faisons dans la liste 12-2.

Nom de fichier : src/main.rs

use std::env;

fn main() {
    let args: Vec<String> = env::args().collect();

    let query = &args[1];
    let file_path = &args[2];

    println!("Searching for {}", query);
    println!("In file {}", file_path);
}

Liste 12-2 : Création de variables pour stocker l'argument de requête et l'argument de chemin de fichier

Comme nous l'avons vu lorsque nous avons imprimé le vecteur, le nom du programme occupe la première valeur dans le vecteur à args[0], donc nous commençons les arguments à l'index 1. Le premier argument que minigrep prend est la chaîne de caractères que nous recherchons, donc nous plaçons une référence au premier argument dans la variable query. Le second argument sera le chemin du fichier, donc nous plaçons une référence au second argument dans la variable file_path.

Nous imprimons temporairement les valeurs de ces variables pour prouver que le code fonctionne comme prévu. Exécutons à nouveau ce programme avec les arguments test et sample.txt :

$ cargo run -- test sample.txt
   Compiling minigrep v0.1.0 (file:///projects/minigrep)
    Finished dev [unoptimized + debuginfo] target(s) in 0.0s
     Running `target/debug/minigrep test sample.txt`
Searching for test
In file sample.txt

Parfait, le programme fonctionne! Les valeurs des arguments dont nous avons besoin sont enregistrées dans les bonnes variables. Plus tard, nous ajouterons une gestion des erreurs pour traiter certaines situations potentielles erronées, telles que lorsque l'utilisateur ne fournit aucun argument ; pour l'instant, nous allons ignorer cette situation et travailler sur l'ajout de capacités de lecture de fichiers.

Summary

Félicitations! Vous avez terminé le laboratoire Accepting Command Line Arguments. Vous pouvez pratiquer d'autres laboratoires dans LabEx pour améliorer vos compétences.