Bir "sayıyı tahmin et" oyununu kodlayarak awk öğrenin
Programlama dilleri birçok ortak özelliği paylaşma eğilimindedir. Yeni bir dil öğrenmenin harika bir yolu tanıdık bir program oluşturmaktır. Bu yazıda tanıdık kavramları göstermek için awk kullanarak bir "sayıyı tahmin et" oyunu oluşturacağım.
Yeni bir programlama dili öğrendiğinizde çoğu programlama dilinin ortak noktalarına odaklanmak iyi bir fikirdir:
- Değişkenler – bilginin saklandığı yerler
- İfadeler – şeyleri hesaplamanın yolları
- İfadeler - durum değişikliklerinin bir programda ifade edildiği araçlar
Bu kavramlar çoğu programlama dilinin temelini oluşturur.
Bu kavramları anladıktan sonra gerisini çözmeye başlayabilirsiniz. Örneğin, çoğu dilin tasarımlarıyla desteklenen bir "işleri yapma yöntemi" vardır ve bu yollar bir programdan diğerine oldukça farklı olabilir. Bu yollar arasında modülerlik (ilgili işlevlerin birlikte gruplandırılması), bildirimsel ve emir kipi, nesne yönelimi, düşük ve yüksek seviyeli sözdizimsel özellikler vb. yer alır. Birçok programcının aşina olduğu bir örnek "tören", yani sorunu çözmeden önce ortamı hazırlamak için gereken çalışma miktarıdır. Java programlama dilinin, tasarımından kaynaklanan ve tüm kodun bir sınıf içinde tanımlanmasını gerektiren önemli bir tören gereksinimine sahip olduğu söyleniyor.
Ama temellere geri dönelim. Programlama dilleri genellikle benzerlikleri paylaşır. Bir programlama dilini öğrendikten sonra, o yeni dildeki farklılıkları anlamak için diğerinin temellerini öğrenerek başlayın.
Devam etmenin iyi bir yolu, bir dizi temel test programı oluşturmaktır. Bunlar ele alındığında öğrenme bu benzerliklerle başlar.
Kullanabileceğiniz bir test programı "sayıyı tahmin et" programıdır. Bilgisayar bir ile yüz arasında bir sayı seçer ve sizden bu sayıyı tahmin etmenizi ister. Program siz doğru bir tahmin yapana kadar döngüye girer.
"Sayıyı tahmin et" programı, programlama dillerindeki çeşitli kavramları kullanır:
- Değişkenler
- Giriş
- Çıktı
- Koşullu değerlendirme
- Döngüler
Bu, yeni bir programlama dili öğrenmek için harika bir pratik deney.
Not: Bu makale, Moshe Zadka'nın Julia ve Jim Hall'un Bash'te bunu yapma hakkındaki makalesindeki bu yaklaşımı kullanarak yapma hakkındaki makalesinden uyarlanmıştır.
awk cinsinden sayıyı tahmin et
Awk programı olarak bir "sayıyı tahmin et" oyunu yazalım.
Awk dinamik olarak yazılmıştır, veri dönüşümüne yönelik bir kodlama dilidir ve etkileşimli kullanım için şaşırtıcı derecede iyi bir desteğe sahiptir. Awk, 1970'lerden beri, başlangıçta Unix işletim sisteminin bir parçası olarak varlığını sürdürüyor. Awk'yi bilmiyorsanız ancak elektronik tabloları seviyorsanız, bu bir işarettir… gidin Awk'u öğrenin!
Awk'u keşfetmenize "sayıyı tahmin et" oyununun bir versiyonunu yazarak başlayabilirsiniz.
İşte benim uygulamam (belirli özelliklerden bazılarını inceleyebilmemiz için satır numaralarıyla birlikte):
1 BEGIN {
2 srand(42)
3 randomNumber = int(rand() * 100) + 1
4 print "random number is",randomNumber
5 printf "guess a number between 1 and 100\n"
6 }
7 {
8 guess = int($0)
9 if (guess < randomNumber) {
10 printf "too low, try again:"
11 } else if (guess > randomNumber) {
12 printf "too high, try again:"
13 } else {
14 printf "that's right\n"
15 exit
16 }
17 }Awk kontrol yapıları ile C veya Java arasındaki benzerlikleri hemen görebiliriz, ancak Python'dan farklıdır. if-then-else veya while gibi ifadelerde, then, else ve while kısımları bir ifadeyi veya { ve içinde yer alan bir ifadeler grubunu alır. Ancak AWk ile ilgili baştan anlaşılması gereken büyük bir fark vardır:
Awk, tasarımı gereği bir veri hattı etrafında inşa edilmiştir.
Bu ne anlama gelir? Çoğu Awk programı, bir girdi satırı alan, verilerle bir şeyler yapan ve bunları çıktıya yazan kod parçacıklarıdır. Böyle bir dönüşüm hattına olan ihtiyacın bilincinde olan Awk, varsayılan olarak tüm dönüşüm tesisatını sağlar. Yukarıdaki program aracılığıyla temel bir soru sorarak bunu inceleyelim: 'Konsoldan veri okuma' yapısı nerede?
Bunun cevabı yerleşiktir. Özellikle 7-17. satırlar Awk'a okunan her satırda ne yapması gerektiğini söyler. Bu bağlam göz önüne alındığında, 1'den 6'ya kadar olan satırların herhangi bir şey okunmadan önce yürütüldüğünü görmek oldukça kolaydır.
Daha spesifik olarak, 1. satırdaki BEGIN anahtar kelimesi bir tür "kalıptır"; bu durumda Awk'a herhangi bir veriyi okumadan önce BEGIN 'den sonra gelen işlemi yürütmesi gerektiğini belirtir. { … } içinde. Bu programda kullanılmayan benzer bir END anahtar sözcüğü, Awk'a her şey okunduğunda ne yapması gerektiğini belirtir.
7 – 17. satırlara dönersek, benzer bir kod bloğu {… } oluşturduklarını görüyoruz, ancak önünde anahtar kelime yok. Awk'un {'den önce eşleşeceği hiçbir şey olmadığından, bu satırı alınan her giriş satırına uygulayacaktır. Her giriş satırı kullanıcı tarafından tahmin olarak girilecektir.
Yürütülen koda bakalım. İlk olarak, herhangi bir girişten önce gerçekleşen giriş bölümü okunur.
2. satırda rasgele sayı üretecini 42 sayısıyla başlatıyoruz (eğer bir argüman sunmazsak sistem saati kullanılır). 42 mi? Elbette 42. 3. satır, 1 ile 100 arasında rastgele bir sayı hesaplar ve 4. satır, hata ayıklama amacıyla bu sayıyı yazdırır. 5. satır kullanıcıyı bir sayıyı tahmin etmeye davet eder. Bu satırın print değil, printf kullandığını unutmayın. C'de olduğu gibi, printf''in ilk argümanı da çıktıyı biçimlendirmek için kullanılan bir şablondur.
Kullanıcı artık programın girdi beklediğini bildiğine göre, konsola bir tahmin yazabilir. Awk, bu tahmini daha önce de belirtildiği gibi 7 – 17. satırlardaki koda iletir. 18. satır giriş kaydını bir tamsayıya dönüştürür; $0 giriş kaydının tamamını belirtirken, $1 giriş kaydının ilk alanını belirtir, < Strong>$2, ikincisi vb. Evet, Awk, varsayılan olarak beyaz boşluk olan önceden tanımlanmış ayırıcıyı kullanarak bir giriş satırını kurucu alanlara böler. 9 ila 15. satırlar tahmini rastgele sayıyla karşılaştırarak uygun yanıtları yazdırır. Tahmin doğruysa, 15. satır giriş hattı işleme hattından zamanından önce çıkar.
Basit!
Awk programlarının belirli giriş satırı yapılandırmalarına tepki veren ve verilerle ilgili şeyler yapan kod parçacıkları şeklindeki alışılmadık yapısı göz önüne alındığında, filtreleme kısmının nasıl çalıştığını görmek için alternatif bir yapıya bakalım:
1 BEGIN {
2 srand(42)
3 randomNumber = int(rand() * 100) + 1
4 print "random number is",randomNumber
5 printf "guess a number between 1 and 100\n"
6 }
7 int($0) < randomNumber {
8 printf "too low, try again: "
9 }
10 int($0) > randomNumber {
11 printf "too high, try again: "
12 }
13 int($0) == randomNumber {
14 printf "that's right\n"
15 exit
16 }1-6. satırlar değişmedi. Ancak şimdi görüyoruz ki 7-9. satırlar, satırın tamsayı değeri rastgele sayıdan küçük olduğunda yürütülen koddur, 10-12. satırlar ise satırın tamsayı değeri rastgele sayıdan büyük olduğunda yürütülen koddur. ve 13 – 16 arasındaki satırlar, ikisi eşleştiğinde yürütülen koddur.
Bu "havalı ama tuhaf" görünebilir; örneğin neden int($0)'i tekrar tekrar hesaplayalım? Ve elbette, sorunu çözmenin tuhaf bir yolu olurdu. Ancak bu modeller, düzenli ifadeleri veya Awk tarafından desteklenen herhangi bir yapıyı kullanabildiklerinden, koşullu işlemeyi ayırmanın gerçekten harika yolları olabilir.
Bütünlüğü sağlamak adına, bu kalıpları, ortak hesaplamaları yalnızca belirli durumlar için geçerli olan şeylerden ayırmak için kullanabiliriz. İşte açıklamak için üçüncü bir versiyon:
1 BEGIN {
2 srand(42)
3 randomNumber = int(rand() * 100) + 1
4 print "random number is",randomNumber
5 printf "guess a number between 1 and 100\n"
6 }
7 {
8 guess = int($0)
9 }
10 guess < randomNumber {
11 printf "too low, try again: "
12 }
13 guess > randomNumber {
14 printf "too high, try again: "
15 }
16 guess == randomNumber {
17 printf "that's right\n"
18 exit
19 }Girdinin hangi değeri gelirse gelsin, tam sayıya dönüştürülmesi gerektiğinin bilincinde olarak, tam da bunu yapmak için 7 – 9 arasındaki satırları oluşturduk. Şimdi, 10 – 12, 13 – 15 ve 16 – 19 numaralı üç satır grubu, her seferinde giriş satırını dönüştürmek yerine önceden tanımlanmış değişken tahminine atıfta bulunur.
Öğrenmek istediklerimiz listesine geri dönelim:
- değişkenler – evet, Awk'ta bunlar var; giriş verilerinin dizeler halinde geldiği ancak gerektiğinde sayısal bir değere dönüştürülebileceği sonucunu çıkarabiliriz
- girdi – Awk, girdileri yalnızca "veri dönüştürme hattı" yaklaşımı aracılığıyla okumaya gönderir
- çıktı – çıktıya bir şeyler yazmak için Awk'ın
printveprintfprosedürlerini kullandık - koşullu değerlendirme – Awk'un if-then-else özelliğini ve belirli giriş hattı yapılandırmalarına yanıt veren giriş filtrelerini öğrendik
- döngüler – ha, bunu hayal edin! Awk'ın benimsediği "veri dönüştürme hattı" yaklaşımı sayesinde bir kez daha burada bir döngüye ihtiyacımız olmadı; döngü "sadece olur." Kullanıcının Awk'a dosya sonu sinyali (Linux terminal penceresi kullanılırken CTRL-D) göndererek işlem hattından zamanından önce çıkabileceğini unutmayın.
Girişi işlemek için bir döngüye ihtiyaç duymamanın önemini düşünmeye değer. Awk'un bu kadar uzun süre geçerli kalmasının bir nedeni, Awk programlarının kompakt olmasıdır ve kompakt olmalarının nedenlerinden biri de konsoldan veya bir dosyadan okumak için gerekli standartların olmamasıdır.
Programı çalıştıralım:
$ awk -f guess.awk
random number is 25
guess a number between 1 and 100: 50
too high, try again: 30
too high, try again: 10
too low, try again: 25
that's right
$Ele almadığımız bir şey yorumlardı. Bir Awk yorumu # ile başlar ve satır sonuyla biter.
Sarmak
Awk inanılmaz derecede güçlüdür ve bu "sayıyı tahmin et" oyunu, başlamanın harika bir yoludur. Ancak bu, yolculuğunuzun sonu olmamalı. Awk'un genişletilmiş bir sürümü olan ve Linux kullanıyorsanız muhtemelen bilgisayarınızda bulunan Awk ve Gawk'ın (GNU Awk) tarihini okuyabilir veya orijinali hakkında her şeyi ilk geliştiricilerinden okuyabilirsiniz.
Ayrıca öğrendiğiniz her şeyi takip etmenize yardımcı olacak yardımcı sayfamızı da indirebilirsiniz.