Kullanıcıdan Girdi Almak

Evet, kullanıcıdan veri girişi almanın vakti geldi diye düşünüyorum. Örneğin Instagram'a giriş yaparken aslında 'kullanıcı adı' ve 'şifre' bölümü bir girdi bölümüdür; sizden bir şeyler girmenizi bekler. Bununla beraber biriyle mesajlaşırken genelde en altta bulunan, mesajı yazdığınız küçük alan da bir girdi alanıdır ve sizden bir şeyler yazmanızı bekler. Dikkat ettiyseniz neredeyse tüm platformlardaki girdi alanlarının ne işe yaradığı kısaca belirtilmiştir. Örneğin bazı platformlarda 'kullanıcı adı' kısmı için 'kullanıcı adı veya telefon' şeklinde bir ibare yer alır ve bu ibare sayesinde siz, oraya kullanıcı adınızı veya telefon numaranızı girmeniz gerektiğini anlarsınız. İşte, bu işi yaparken hem kontrollerinizi iyi yapmalı hem de kullanıcıyı bilgilendirmelisiniz.

Şu ana dek normal şartlarda biz, değişkenleri de değerleri de belirleyen taraftık. Örneğin bir 'isim' değişkenini tanımlıyor, değerini de biz belirliyorduk:

Peki, bizim bir değişkenimiz olsa ve bu değişkenin değerini kullanıcıdan alsak daha efektif olmaz mıydı? Elbette. İşte, bu iş için Bash içerisinde 'read' isimli bir komutumuz var. Read kelimesi İngilizce'den gelir ve 'Oku' anlamını taşır. Buradan da anlayacağınız üzere bu komut, kullanıcının girdiği veriyi okuyacaktır. Nasıl kullanıldığına hemen bakalım.

Kullanıcıdan girdi almak için ilk önce neyi istediğimi belirtmemiz lazım. Öylece girdi beklersek kullanıcı ne girmesi gerektiğini zaten bilemeyecektir. Dolayısıyla ilk adım olarak sağ tarafta gördüğünüz komutta kullanıcıya 'Adın ne?' şeklinde bir soru yönelttik ve kodu çalıştırdığımızda bir problem ile karşılaşmadık.

Daha sonra sadece 'read name' şeklinde bir ifade yazdık ve kodu çalıştırdık. Kodu çalıştırdığımızda bize yine ismimizi sordu ama bu sefer bir şeyler yazmamızı ve Enter tuşuna basmamızı bekledi. Daha sonra Cyberworm şeklinde bir şey yazdım ve Enter tuşuna bastım; program kapandı. Demek ki kullanıcıdan artık veri girişi alabiliyoruz.

Dikkat edin; burada, read $name şeklinde bir kullanım yapmadık çünkü herhangi bir değişken çağırmıyoruz. Bu komutta aslında yeni bir değişken tanımlamış oluyoruz ama sıradan değişkenlere nazaran bunu, "okunacak olan değişken" şeklinde ifade edebiliriz. İşte, bu yüzden biz, name="Cyberworm" komutuyla neredeyse aynı işi yapan bir tanımlama gerçekleştiriyoruz: 'read name'. Sadece bunu, 'okunacak olan bir değişken' sıfatına sokuyoruz. Şimdi, bir sonraki adıma geçelim.

Bir sonraki adımımız ne olabilir? Az önce, ismimizi yazdıktan sonra program kapanıyordu. Şimdi; kullanıcı, adını girdiğinde ona neler olduğunu söyleyebiliriz. Örneğin kullanıcıya, onun ismiyle hitap ederek bir 'Hoş Geldin' mesajı verebiliriz. Hemen yapalım.

Şimdi, dikkat ederseniz $name şeklinde bir kullanım gerçekleştirdik. Az önce 'okunacak olan değişken' tanımladık ve şu an onu çağırıyoruz. Çıktı kısmına tekrardan ismimi yazdım ve çıktı kısmına "You're welcome" yazdı. Hemen yanında da biraz önce tanımladığımız ve şimdi çağırdığımız değişkenin değerini yani girdiğimiz değeri görüyorsunuz.

Bu noktada aklınıza takılan bir soru olabilir. Örneğin "'You're welcome, Cyber Worm' cümlesinin sonunda neden nokta yok ve bu sorunu nasıl aşabiliriz?" Bu sorunu, $name şeklinde çağırdığımız değişkeni, tırnak işaretlerinin içine koyarak sağlayabilirsiniz. Hemen görelim.

$name komutunu tırnaklar içerisine koydum ve en sona da bir nokta koydum. Bunun sonucunda çıktımız daha düzgün bir hâl aldı. Peki, bir önceki blogumuzda her tipi kendine has bir şekilde yazmamız gerektiğini söylemiştik; şimdi neden bir değişkeni tırnaklar içerisine yazıyoruz?

Mantıklı bir sorudur ama benim de mantıklı bir cevabım var. $name komutu şuan, başındaki '$' ifadesi sayesinde tanımlayıcı niteliktedir. Yani bu ifadeyi bir string içerisine yazmış olsanız bile başındaki işaret sayesinde bunun görevi de amacı da bir soruna yol açmıyor. Zaten dikkat edin; rengi de hâlâ mor renkte.

Şimdi, aslında biraz dikkat ettiğinizde bir sorunumuz daha olduğunu göreceksinizdir:

Bizden bir girdi beklendiğinde bu girdinin, yeşil ok ile gösterdiğim yerden alınması gerekmez mi; sonuç olarak ekranda bir soru var ve bunun cevabını, sorunun yanına yazmamız gerekmez mi? Evet, öyle ama şu an kırmızı ok ile işaretlediğim kısımdan devam ediyor; bunu çözmemiz lazım.

Blogumuz, bir konuyu anlatmak için anlatmaz; öğretmek için anlatır. Dolayısıyla birçok şeyi sürekli olarak bu bloglara bakarak yapmaktansa nasıl yapacağınızı ve sıkıştığınızda nasıl bir yol izleyebileceğinizi de anlatıyoruz. Şimdi, bizim girdi alma komutumuz 'read'; artık biliyorsunuz. Fakat bu komutun, yeni satırdan yani bir alt satırdan veri girişi istemek gibi kötü bir huyu var ve biz, bunu düzeltmek istiyoruz ama nasıl yapacağımızı bilmiyoruz. Bunun için, 'Kali'yi Tanıyalım' isimli blogumuzda da bahsettiğimiz '--help' komutunu kullanabilir ve yardım alabiliriz. O yüzden terminal ekranına 'read --help' şeklinde bir komut veriyorum ve bu komut bana, read komutu hakkında neler yapabileceğimi anlatıyor.

Yukarıdaki görselde alt taraflarda kırmızı kutu içerisine aldığım bir kısım var. Burada, read komutunun alabileceği '-p' şeklinde bir parametre olduğunu görüyoruz. Açıklama kısmını okuyabiliriz ama şimdilik yeşil çizgi ile altını çizdiğim kısma bakalım: 'without a trailing newline' yani ' sonunda yeni satır olmadan' şeklinde bir bilgilendirme söz konusu. Dolayısıyla ben, read -p name şeklinde bir kullanım yaparsam bu sorunu çözebilirim, öyle değil mi? Hemen deneyelim.

Dikkat edin; biraz önceki ekran görüntülerinde ilk satırda 'echo "What is your name? >"' şeklinde bir kodumuz vardı ve hemen altında read komutumuz yer alıyordu. Şimdi, read komutu içerisine -p parametresini verdik ama bu parametreyle beraber yukarıdaki gibi soracağımız soruyu da vermek zorundayız. Yani; 'read -p "soracağımız soru" name' şeklinde bir kullanım yaptık. Bu, her şartta daha verimli bir kullanım oldu. Hem gereksiz kod satırlarını yok edip tek bir satırda hepsini birleştirdik hem de daha anlaşılır bir kod yapısı oluştu. Yani read için bir parametre verecekseniz bunu, oraya metinsel bir ifade koyarak desteklemelisiniz.

Çıktı kısmına baktığımızda ise sorunumuzun çözüldüğünü, artık sorunun hemen yanına cevap yazabileceğimizi ve çıktı kısmında da herhangi bir sorun olmadığını görüyorsunuz.

read komutu aslında çok işlevli bir komuttur. Biraz önce basit bir şekilde read name dedik fakat bu komuta, birden fazla değişken de verebiliriz. Ne demek istiyorum?

Yukarıda gördüğünüz gibi kullanıcıya adını ve soyadını sorduk. Bununla beraber -p parametremiz ve metnimiz yerinde duruyor. Bunların hemen yanına da iki adet okunacak değişken yazdık. Daha sonra echo komutu ile bu iki okunacak değişken çağırdık.

Çıktı kısmına baktığımızda, çıktının aynı olduğunu görüyoruz. Az önce Cyber Worm, sadece name isimli değişkeni temsil ediyordu. Buradaki tek fark, Cyber kelimesinin name, Worm kelimesinin ise surname değişkenini temsil ettiğidir.

Bunu daha iyi anlamak adına isterseniz bir de yaş değişkeni ekleyelim.

Bu sefer; name, surname ve age isimli üç okunacak değişkenimiz var. Daha sonra normal bir metin olarak söyleyeceklerimizi yazdık ve metnin içerisinde, olması gereken yerlere değişkenlerimizi çağırdık. Çıktı kısmında da gayet net ve güzel bir çıktımız olduğunu görüyorsunuz.

Yalnız şuraya dikkat edin; read komutu ile kaç adet değişken tanımlamışsam programı çalıştırırken her değişkene bir değer veriyorum.

Peki, sizce yukarıda yaptığımızın daha sağlıklı ve kolay bir yolu var mıdır? Evet, diziler (arrays). Bash'te bulunan array yapısını daha ileriki zamanlarda çok daha detaylı bir şekilde ele alacağız. Ancak şimdi anlatacağım konu için array mantığı lazım olduğu için bunu size veriyorum. Diziler, birden fazla veriyi tek başına saklayabilen yapılardır. Programlama camiasında da 'index' dediğimiz bir yapı vardır. Bu yapıda, saymaya 1'den değil 0'dan başlanır. Yani ilk eleman aslında sıfırıncı elemandır. Bunu, aşağıdaki görsel sayesinde daha iyi kavrayabilirsiniz:

Şimdi, biraz önce çalıştırdığımız '--help' komutunda karşımıza çıkan parametrelerden birini daha görelim: '-a'. Bu parametre ile, tek bir dizi (array) ismi belirleyip o diziye çeşitli elemanlar ekleyebiliyor ve bunları yazdırabiliyoruz.

Şimdi, bunu nasıl yaptığımıza bir bakalım.

Yukarıdaki ifadeyi parçalayarak anlamaya çalışalım. 'read -p "What is your full-name: "' kısmı, zaten biraz önce anlattığımız kısımdır. Bu kısım, kullanıcının, gireceği veriyi aynı satıra girmesini sağlıyordu.

Bu kısımdan hemen sonra ise '-a nameAndSurname' şeklinde bir ifade yazmışız. Buradaki '-a' ifadesi bir diziyi (array) ifade eder. Bununla beraber bu parametre, kendisinden sonra gelecek olan ismin (nameAndSurname) aslında bir dizinin ismi olacağını anlatır. Bu kısım aşağıdaki kod ile aynı işi yapar:

nameAndSurname=<dizi>

Kodun tamamını incelediğimizde şunu diyebiliriz: "Aslında kullanıcının gireceği verileri tek seferde, daha az zahmetle ve aynı satır içerisinde alabiliyoruz."

Bu kısmı anladığımıza göre şimdi bunları işletelim.

Bu noktada biz, kullanıcıya adını ve soyadını soruyoruz. Dolayısıyla biri isim biri de soy isim olmak üzere iki adet veri girecektir. Elbette kişinin ikinci bir ismi de olabilir ama bu koşullara ileriki zamanlarda bakacağız. Bu iki veriyi, biraz önce verdiğim görsel ile bağdaştırmaya çalışın. Yani aslında buradaki 'isim' değişkeni dizinin sıfırıncı index'i, 'soy isim' değişkeni ise dizinin birinci index'i şeklindedir, öyle değil mi? Aşağıdaki görsel yardımcı olabilir.

İşte, aşağıdaki kodu bunun gibi düşünmenizi istiyorum.

Aslında buradaki echo yapısını zaten biliyorsunuz; bizim derdimiz mor kısımlarla. Şimdi, ilk mor kısma bakalım: '${nameAndSurname[0]}'. Bu koddaki dolar ($) işaretiyle diziyi çağırdığımızı biliyorsunuz. Şimdi bunu parçalayarak öğrenelim.

$ işaretinden hemen sonra bir süslü parantez '{}' açıyoruz: '${}'.

Süslü parantezlerin içerisine, biraz önce tanımladığımız dizinin ismini veriyoruz: '${nameAndSurname}'.

Hemen sonrasında ise dizi isminin yanına bir adet köşeli parantez de açıp kapatıyoruz: '${nameAndSurname[]}'.

Son olarak, biraz önce bahsettiğimiz index yapısını aklımıza getiriyoruz ve istediğimiz 'isim' değişkeninin aslında sıfırıncı index olduğunu biliyoruz. Dolayısıyla o köşeli parantezin içerisine '0' yazıyoruz. Bu kod bize, kullanıcının ismini getirecektir. 

Diğer mor kısma baktığımızda aynı şeyleri, aynı mantığı uyguladığımızı görüyoruz. Buradaki tek fark, '0' yerine '1' yazmamızdır. Buradaki '1' ifadesi de 'soy isim' içindir. İsterseniz kodu çalıştırıp neler olacağına bakalım.

Gördüğünüz gibi yukarıda isim ve soy isim yerine geçecek iki ifade yazdım; 'Cyber' isim olacak, 'Worm' ise soy isim olacak.

Gördüğünüz gibi sorunsuz bir şekilde çalıştı. Şimdi, biraz önce "bunu yazıyoruz, süslü parantez açıyoruz" ve benzeri ezber ifadeler kullandım. Bunun sebebi syntax yapısıdır. Yani bunun böyle yazılması gerekiyor; bu, bir kuraldır. Syntax hakkında daha net bilgiler için buyurun: Syntax Nedir?

Buradan anlamamız gereken bir başka konu ise 'read' komutunun genişliğidir. Blogun başında 'çok işlevli' olduğundan söz etmiştim. Gördüğünüz gibi 'read' komutuyla birden fazla parametreyi karışık biçimde kullanabiliyoruz. Siz de lütfen 'read --help' yazarak veya interneti tarayarak daha fazla pratik yapmaya çalışın. Evet, anladınız ama pratik yoksa bu anlattıklarım yakın zamanda hafızanızdan silinecektir.

Son olarak size bir hareket daha göstermek istiyorum. 'read' komutunda sadece '-p' ifadesini kullanarak da kullanıcının yazdığı şeyleri görebiliriz. Yani bir array tanımlayıp değerleri oraya aktarıp onu görmek yerine bunu, başka bir şekilde de yapabiliriz. Hemen bakalım.

Sistem değişkenleri konusuna gittik. read komutuna hiçbir şey eklemeden de kullanıcının yazdığı her şeyi görebilmek için '$REPLY' sistem değişkenini çağırıyoruz. Çıktı kısmında da görebileceğiniz üzere ismimi yazdım ve yazdıklarım bana gösterildi.


Yayınlanma Tarihi: 2022-09-03 14:52:22

Son Düzenleme Tarihi: 2022-09-08 15:35:08