Komut Satırı Argümanlarını Kabul Etme

Her zaman olduğu gibi cargo new ile yeni bir proje oluşturalım. Sisteminizde mevcut olabilecek grep aracıyla çakışmaması için projemizi minigrep olarak adlandıracağız

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

İlk görev, minigrep'in iki komut satırı argümanını kabul etmesini sağlamaktır: dosya adı ve aranacak bir dize. Yani, programımızı cargo run'la, aranacak bir dize ve aranacak bir dosyanın yolu ile çalıştırabilmek istiyoruz, şunun gibi:

$ cargo run searchstring example-filename.txt

Şu anda, cargo new tarafından oluşturulan program, ona verdiğimiz argümanları işleyemiyor. crates.io'daki bazı mevcut kütüphaneler, komut satırı argümanlarını kabul eden bir program yazmaya yardımcı olabilir, ancak bu kavramı yeni öğrendiğiniz için, hadi bunu kendimiz sürekleyelim.

Argüman Değerlerini Okumak

minigrep'in kendisine ilettiğimiz komut satırı argümanlarının değerlerini okumasını sağlamak için, Rust'ın standart kütüphanesinde bulunan std::env::args fonksiyonuna ihtiyacımız olacak. Bu fonksiyon, minigrep'e iletilen komut satırı argümanlarının bir yineleyicisini döndürür. Bölüm 13'te yineleyicileri tam olarak ele alacağız. Şimdilik, yineleyiciler hakkında yalnızca iki ayrıntıyı bilmeniz gerekir: yineleyiciler bir dizi değer üretir ve bir yineleyicide onu bir koleksiyona dönüştürmek için collect metodunu çağırabiliriz, örneğin: yineleyicinin ürettiği tüm öğeleri içeren vektör.

Liste 12-1'deki kod, minigrep programınızın kendisine iletilen herhangi bir komut satırı argümanını okumasını ve ardından değerleri bir vektörde toplamasını sağlar.

Dosya adı: src/main.rs

use std::env;

fn main() {
    let args: Vec<String> = env::args().collect();
    println!("{:?}", args);
}

Liste 12-1: Komut satırı argümanlarını bir vektörde toplama ve yazdırma

İlk olarak, args fonksiyonunu kullanabilmemiz için std::env modülünü use ifade yapısı ile kapsama alıyoruz. std::env::args fonksiyonunun iki modül düzeyinde tutuluyor olduğuna dikkat edin. Bölüm 7'de tartıştığımız gibi, istenen fonksiyonun birden fazla modülde iç içe olduğu durumlarda, ana modülü fonksiyon yerine kapsama almak gelenekseldir. Bunu yaparak, std::env'deki diğer fonksiyonları kolayca kullanabiliriz. Ayrıca use std::env::args eklemekten ve ardından fonksiyonu yalnızca args ile çağırmaktan daha az belirsizdir, çünkü arg'ler kolayca geçerli modülde tanımlanan bir fonksiyonla karıştırılabilir.

args Fonksiyonu ve Geçersiz Unicode

Herhangi bir argüman geçersiz Unicode içeriyorsa std::env::args öğesinin panikleyeceğini unutmayın. Programınızın geçersiz Unicode içeren argümanları kabul etmesi gerekiyorsa, bunun yerine std::env::args_os kullanın. Bu fonksiyon, String değerleri yerine OsString değerleri üreten bir yineleyici döndürür. Basitlik için burada std::env::args kullanmayı seçtik, çünkü OsString değerleri platforma göre farklılık gösterir ve onlarla çalışmak String değerlerinden daha karmaşıktır.

main'in ilk satırında, env::args'ı çağırırız ve yineleyiciyi yineleyici tarafından üretilen tüm değerleri içeren bir vektöre dönüştürmek için collect kullanırız. Pek çok türde koleksiyon oluşturmak için collect fonksiyonunu kullanabiliriz, bu nedenle bir dizi vektörü istediğimizi belirtmek için açıkça arg türüne açıklama ekleriz. Rust'ta türlere çok nadiren açıklama eklememiz gerekse de, collect, genellikle açıklama eklemeniz gereken bir fonksiyondur çünkü Rust, istediğiniz koleksiyon türünü çıkaramaz.

Son olarak, vektörü hata ayıklama biçimlendiricisini (:?) kullanarak yazdırırız. Kodu önce bağımsız değişken olmadan ve ardından iki bağımsız değişkenle çalıştırmayı deneyelim:

$ cargo run
   Compiling minigrep v0.1.0 (file:///projects/minigrep)
    Finished dev [unoptimized + debuginfo] target(s) in 0.61s
     Running `target/debug/minigrep`
["target/debug/minigrep"]
$ cargo run needle haystack
   Compiling minigrep v0.1.0 (file:///projects/minigrep)
    Finished dev [unoptimized + debuginfo] target(s) in 1.57s
     Running `target/debug/minigrep needle haystack`
["target/debug/minigrep", "needle", "haystack"]

Vektördeki ilk değerin, ikili dosyamızın adı olan "target/debug/minigrep" olduğuna dikkat edin. Bu, programların yürütülürken çağrıldıkları adı kullanmasına izin vererek, C'deki argüman listesinin davranışıyla eşleşir. Mesajlarda yazdırmak veya programı çağırmak için hangi komut satırı diğer adının kullanıldığına bağlı olarak programın davranışını değiştirmek istemeniz durumunda, program adına erişiminiz olması genellikle uygundur. Ancak bu bölümün amaçları doğrultusunda, onu görmezden geleceğiz ve yalnızca ihtiyacımız olan iki argümanı kaydedeceğiz.

Değişkenlerde Argüman Değerlerini Tutma

Program şu anda komut satırı argümanları olarak belirtilen değerlere erişebilir. Şimdi değerleri programın geri kalanında kullanabilmemiz için iki argümanın değerlerini değişkenlere kaydetmemiz gerekiyor. Bunu Liste 12-2'de yapıyoruz.

Dosya adı: src/main.rs

use std::env;

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

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

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

Liste 12-2: Sorgu argümanını ve dosya adı argümanını tutmak için değişkenler oluşturma

Vektörü yazdırdığımızda gördüğümüz gibi, programın adı args[0]'daki vektördeki ilk değeri alır, dolayısıyla argümanları indeks 1'den başlatıyoruz. minigrep'in aldığı ilk argüman, aradığımız dizgidir, bu yüzden değişken sorgusundaki ilk argümana bir referans koyduk. İkinci argüman dosya adı olacaktır, bu yüzden dosya adı değişkenine ikinci argümana bir referans koyduk.

Kodun istediğimiz gibi çalıştığını kanıtlamak için bu değişkenlerin değerlerini geçici olarak yazdırırız. Bu programı test ve sample.txt argümanları ile tekrar çalıştıralım:

$ 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

Harika, program çalışıyor! İhtiyacımız olan argümanların değerleri doğru değişkenlere kaydediliyor. Daha sonra, örneğin kullanıcının hiçbir argüman sağlamaması gibi bazı olası hatalı durumlarla başa çıkmak için bazı hata işleme ekleyeceğiz, şimdilik bu durumu görmezden geleceğiz ve bunun yerine dosya okuma yetenekleri eklemeye çalışacağız.