Shell Scripts: Case Komutu
Linux Shell Script Geliştirmek diye başladığım yazı dizisinin
bir diğer yazısında daha birlikteyiz. if/elif/else
komutlarını sık sık kullanmaya başladığınızda farkedeceksiniz ki,
bir çok zaman tek bir değişkenin değerini kontrol ediyoruz.
Örneğin komut satırından gelen parametrenin değeri 1 ise şunu yap, 2 ise bunu yap, 3 ise başka birşey yap.
Böyle tek bir değişkeni kontrol etmemiz gerektiğinde if/elif/else
yazmak çok sıkıcı bir hale dönüşebiliyor.
Peki değişkenin ismini sadece bir kere yazsak ve alabileceği her değer için sadece çalışacak kodları söylesek?
Bu gibi durumlarda işimizi kolaylaştırması için case
adında hoş bir kontrol komutumuz var.
Örneğin komut satırından geçilen bir parametrenin değeri “disk” ise disk istatistiklerini,
“memory” ise bellek istatistiklerini göstermek istiyorsunuz.
Şu şekilde yazabilirsiniz bu programı:
#!/bin/bash
# HelloWorld Application 7
# case
case $1 in
disk ) df ;;
memory ) free ;;
* ) echo "Please enter disk or memory" ;;
esac
Bu programı case ismiyle kaydedip daha sonra ./case disk
diye çalıştırırsak, df
komutu çalışacak.
./case memory
şeklinde çalıştırırsak, free
komutu çalışacak.
Eğer başka bir parametre ile çağırırsak, hata mesajı gösterilecek. En sonraki “*” anahtar kelimesi, disk ve memory dışındaki herşeyle eşleşiyor.
Aşağıdaki şekilde uzun uzun yazmak da mümkün. Her bir durum için birden fazla komut girilebilir.
#!/bin/bash
# HelloWorld Application 8
# case
case $1 in
disk )
echo "Disk stats will be printed."
df
echo "Disk stats were printed."
;;
memory )
echo "Memory stats were printed."
free
echo "Memory stats were printed."
;;
* )
echo "Please enter disk or memory"
;;
esac
Örneğin komut satırından alacağımız 5 tane parametre olsun fakat bu parametrelerin sırası bizi hiç ilgilendirmesin. Mesela bilgisayarımızda o anda çalışan işlemlerin kaydını bir dosyaya yazalım.
- Programımızın ismi processes olsun
-f filename
parametresi geçilirse kullanıcının girdiği isimde bir dosya yaratılsın ve output oraya kaydedilsin.- Dosya ismi parametre geçilmezse, şu anki tarih ve saat ile bir dosya yaratalım.
-z
parametresi geçilirse outputu kaydettiğimiz dosyayı gzip ile zipleyelim.-p
parametresi geçilirse outputu ekrana da yazdıralım.-q searchString
parametresi girilirse, içinde sadece aranan keyword geçen processlerin outputu alalım.--help
parametresi girilirse, programın nasıl kullanılacağını anlatan bir metin gösterip diğer parametreleri yoksayacağız.
Anlayacağınız üzere, komut satırından birkaç tane parametre gelişigüzel girilecek. Girilip girilmemeleri ve hangi sırayla girilecekleri tamamen kullanıcıya kalmış.
#!/bin/bash
# Learning case/esac
DATE=$(date +"%Y_%m_%d-%H_%M_%S")
output_file="proc_$DATE"
useGzip="false"
printOutput="false"
searchText=""
# Read all parameters
until [[ "$#" = "0" ]]; do
case "$1" in
-f )
shift
output_file="$1"
;;
-z )
useGzip="true"
;;
-p )
printOutput="true"
;;
-q )
shift
searchText="$1"
;;
--help|* )
echo "Welcome to our little processes program"
echo "Here are some options you may like:"
echo " -f <filename> : change the name of output file"
echo " -z : gzip the output file"
echo " -p : print the output to the console"
echo " -q <searchTxt> : show lines only containing searchTxt"
echo " --help : prints this help message"
exit
;;
esac
shift
done
processes=""
# Does user want filtering the output?
if [[ "$searchText" = "" ]]; then
# No filtering
processes=$(ps -ef)
else
# Filter lines using grep and searchText
processes=$(ps -ef | grep "$searchText")
fi
# Should I print output to console?
if [[ "$printOutput" = "true" ]]; then
echo "$processes"
fi
# Write output to the file
echo "$processes" > "$output_file"
# Should I use gzip?
if [[ "$useGzip" = "true" ]]; then
# Gzip the output file
gzip "$output_file"
fi
Döngü ile parametreleri okuyup parametreleri shift
komutuyla kaydırmayı
While ve Until Döngüleri isimli yazımda yazmıştım.
Yukarıdaki until döngüsü de aynı şekilde shift yöntemi ile tüm parametreleri okuyor
ve parametrelerin değerini kontrol etmek için case
komutunu kullanıyor.
Parametrelerin değerlerini kontrol ettikten sonra uygun değişkenlerin değerlerini değiştiriyoruz.
Örneğin -p
parametresini gördüğümüzde, printOutput
isimli değişkenin değerini true
yapıyoruz.
Programın ilerleyen kısımlarında bu değişkeni kontrol ediyoruz ve değeri true
ise çıktıyı ekrana yazdırıyoruz.
Nasıl buldunuz case
komutunu?
Parametreleri bu şekilde okuduğumuzda hem kullanıcıyı parametreleri belli bir sırayla girmek zorunda bırakmıyoruz,
hem de kodumuz daha şık görünüyor.
Bu programı aşağıdaki kombinasyonlarla kullanabilirsiniz:
./processes -f myoutput.txt
./processes -z -p
./processes -q java -p -f javaprocesses.out
./processes --help
./processes -p -f somefile.log -z -q chrome
Eğer aynı bir işlemi birden fazla değerle yapmak istiyorsanız,
bunu da pipe(|
) işareti kullanarak belirtebiliyorsunuz.
Mesela yukarıdaki kodda bazı alternatifler ekleyebiliriz.
Aşağıdaki gibi, parametre seçeneklerimize eşanlamlı seçenekler ekleyelim:
-f
yerine--file
kullanılabilsin.-p
yerine--print
kullanılabilsin.-q
yerine--query
kullanılabilsin.-z
yerine--zip
kullanılabilsin.
Bu durumda yukarıdaki kodun case
kısmı aşağıdaki gibi şekillenecek:
case "$1" in
-f|--file )
shift
output_file="$1"
;;
-z|--zip )
useGzip="true"
;;
-p|--print )
printOutput="true"
;;
-q|--query )
shift
searchText="$1"
;;
--help|* )
echo "Welcome to our little processes program"
echo "Here are some options you may like:"
echo " -f | --file <filename> : change the name of output file"
echo " -z | --zip : gzip the output file"
echo " -p | --print : print the output to the console"
echo " -q | --query <searchTxt> : show lines only containing searchTxt"
echo " --help : prints this help message"
exit
;;
esac
Ve bu programı aşağıdaki şekillerde de kullanabiliyoruz artık:
./processes --file myoutput.txt
./processes --zip --print
./processes --query java --print --file javaprocesses.out
./processes --help
./processes --print -f somefile.log -z --query chrome
Bu gecelik anlatmak istediklerim de bu kadar sayın seyirciler. Umarım işlerinizi çılgınca hızlandırabilecek Shell Script’ler yazabilirsiniz.