Sayısal aralıklara harf notları atamak için bir kabuk komut dosyası nasıl yazılır?


19

Sizi 0-100 arasında bir sayı soracak bir komut dosyası yapmak ve sonra numaraya göre not vermek istiyorum.

Ben bash istiyorum.

PS3='Please enter your choice: '
(Something here)

do
case $
    "0-59")
        echo "F"
        ;;
    "60-69")
        echo "D"
        ;;
    "70-79")
        echo "C"
        ;;
    "Quit")
        break
        ;;
    *) echo invalid option;;
esac
done

Yanıtlar:


20

Kısa ve Okunabilirlik: Orta Bir Zemin

Gördüğünüz gibi, bu sorun orta derecede uzun ve biraz tekrarlayıcı ancak son derece okunabilir çözümlere ( terdon ve AB'nin bash cevapları) yanı sıra çok kısa ama sezgisel olmayan ve çok daha az kendi kendini belgeleyen çözümlere (Tim'in pitonu) ve bash cevapları ve glenn jackman'ın perl cevabı ). Tüm bu yaklaşımlar değerlidir.

Bu sorunu ayrıca, kompaktlık ve okunabilirlik arasındaki sürekliliğin ortasında kodla da çözebilirsiniz. Bu yaklaşım, küçük, ezoterik çözümlere daha yakın bir uzunlukla neredeyse daha uzun çözeltiler kadar okunabilir.

#!/usr/bin/env bash

read -erp 'Enter numeric grade (q to quit): '
case $REPLY in [qQ]) exit;; esac

declare -A cutoffs
cutoffs[F]=59 cutoffs[D]=69 cutoffs[C]=79 cutoffs[B]=89 cutoffs[A]=100

for letter in F D C B A; do
    ((REPLY <= cutoffs[$letter])) && { echo $letter; exit; }
done
echo "Grade out of range."

Bu bash çözümüne, okunabilirliği artırmak için bazı boş satırlar ekledim, ancak daha da kısa olmasını isterseniz bunları kaldırabilirsiniz.

Boş satırlar bundan daha aslında sadece biraz daha kısa olan, dahil bir compactified, hala oldukça okunabilir varyant arasında AB'nin bash çözümü . Bu yönteme göre ana avantajları:

  • Daha sezgisel.
  • Notlar arasındaki sınırları değiştirmek (veya ek notlar eklemek) daha kolaydır.
  • Ön ve arka boşlukları olan girdileri otomatik olarak kabul eder (nasıl (( ))çalıştığının açıklaması için aşağıya bakın ).

Bu avantajların üçü de ortaya çıkar çünkü bu yöntem kullanıcının girdisini, kurucu basamaklarını manuel olarak incelemek yerine sayısal veri olarak kullanır.

Nasıl çalışır

  1. Kullanıcının girdisini okuyun. Girdikleri metin içinde hareket etmek için ok tuşlarını kullanmalarına izin verin ( -e) ve \bir kaçış karakteri ( -r) olarak yorumlamayın .
    Bu komut dosyası, zengin özelliklere sahip bir çözüm değildir - ayrıntılandırma için aşağıya bakın - ancak bu kullanışlı özellikler yalnızca iki karakter daha uzun olmasını sağlar. Hep kullanmanızı tavsiye -rile readsize kullanım tedarik izin vermelisiniz bilmedikçe, \kaçar.
  2. Kullanıcı yazdıysa qveya Qçıkın.
  3. Bir oluşturma , birleştirici bir dizi ( declare -A). Her harf notuyla ilişkili en yüksek sayısal notla doldurun.
  4. Döngü aracılığıyla kullanıcı tarafından sağlanan sayı her harf o derecenin sayısal aralığına düşmek yeterince düşük olması durumunda kontrol en düşükten en yükseğe kadar Harf notları,.
    İle (( ))aritmetik değerlendirme, değişken adları ile genişletilmiş olması gerekmez $. (Diğer çoğu durumda, değişkenin değerini yerine kullanmak istiyorsanız, bunu yapmanız gerekir .)
  5. Aralıkta kalırsa, sınıfı yazdırın ve çıkın .
    Kısacası, - yerine kısa devre ve operatör ( &&) kullanıyorum .ifthen
  6. Döngü biterse ve hiçbir aralık eşleşmediyse, girilen sayının çok yüksek olduğunu (100'ün üzerinde) varsayalım ve kullanıcıya aralık dışında olduğunu söyleyin.

Tuhaf Girdi ile Bu Nasıl Davranıyor

Yayınlanan diğer kısa çözümler gibi, bu komut dosyası bir sayı olduğunu varsaymadan girişi kontrol etmez. Aritmetik değerlendirme ( (( ))) otomatik olarak, yani ön ve arka boşluk şeritler de bu sorun, ancak:

  • Hiç sayı gibi görünmeyen girdi 0 olarak yorumlanır.
  • Sayıya benzeyen (yani bir rakamla başlıyorsa) ancak geçersiz karakterler içeriyorsa, komut dosyası hata verir.
  • İle başlayan Çok basamaklı giriş 0edilir olarak yorumlanır içinde sekizlik . Örneğin, komut dosyası 77'nin bir C olduğunu, 077 ise bir D olduğunu söyleyecektir, ancak bazı kullanıcılar bunu isteyebilir, ancak büyük olasılıkla istemez ve karışıklığa neden olabilir.
  • Artı tarafta, aritmetik bir ifade verildiğinde, bu komut dosyası bunu otomatik olarak basitleştirir ve ilişkili harf derecesini belirler. Örneğin, size 320/4'ün B olduğunu söyleyecektir.

Genişletilmiş, Tam Özellikli Sürüm

Bu nedenlerle, girdinin iyi olup olmadığını kontrol eden ve diğer bazı geliştirmeleri içeren bu genişletilmiş komut dosyası gibi bir şey kullanmak isteyebilirsiniz.

#!/usr/bin/env bash
shopt -s extglob

declare -A cutoffs
cutoffs[F]=59 cutoffs[D]=69 cutoffs[C]=79 cutoffs[B]=89 cutoffs[A]=100

while read -erp 'Enter numeric grade (q to quit): '; do
    case $REPLY in  # allow leading/trailing spaces, but not octal (e.g. "03") 
        *( )@([1-9]*([0-9])|+(0))*( )) ;;
        *( )[qQ]?([uU][iI][tT])*( )) exit;;
        *) echo "I don't understand that number."; continue;;
    esac

    for letter in F D C B A; do
        ((REPLY <= cutoffs[$letter])) && { echo $letter; continue 2; }
    done
    echo "Grade out of range."
done

Bu hala oldukça kompakt bir çözüm.

Bu hangi özellikleri ekliyor?

Bu genişletilmiş komut dosyasının temel noktaları şunlardır:

  • Giriş doğrulama. Terdon senaryosu kontrol girişi ile , bir kullanıcının ön ve sonunda boşluk ve kudreti veya sekizli olarak tasarlandığı olmayabilir bir ifade kabul etmeme girmek için izin daha sağlamdır, kurban bir kısalık, ancak başka bir yol gösterir, böylece (sıfır olmadığı sürece) .if [[ ! $response =~ ^[0-9]*$ ]] ...
  • Kullandığım caseile globbing genişletilmiş yerine [[birlikte =~ düzenli ifade eşleştirme (olduğu gibi operatör Terdon cevabı ). Bunu (ve nasıl) bu şekilde yapılabileceğini göstermek için yaptım. Globs ve regexps, metinle eşleşen desenleri belirtmenin iki yoludur ve her iki yöntem de bu uygulama için uygundur.
  • Gibi AB'nin bash komut , ben (ilk yaratılış dışında bir dış döngü içinde her şeyi ekte cutoffsdizisi). Rakamlar ister ve terminal girişi mevcut olduğu ve kullanıcı bunu bırakmasını söylemediği sürece ilgili harf notlarını verir. Bakılırsa do... doneBunu istiyor gibi, söz konusu kod etrafında görünüyor.
  • Bırakmayı kolaylaştırmak için, qveya büyük / küçük harfe duyarlı olmayan herhangi bir varyasyonu kabul ediyorum quit.

Bu komut dosyası acemilere aşina olmayan birkaç yapı kullanır; aşağıda detaylandırılmıştır.

Açıklama: Kullanımı continue

Dış whilehalkanın gövdesinin geri kalanını atlamak istediğimde , continuekomutu kullanıyorum. Bu, daha fazla girdi okumak ve başka bir yineleme çalıştırmak için onu döngünün tepesine geri getirir.

Bunu ilk yaptığımda, içinde olduğum tek döngü dış whiledöngüdür, bu yüzden continueargüman olmadan çağırabilirim . (Ben bir caseyapıdayım, ama bu breakveya işlevini etkilemez continue.)

        *) echo "I don't understand that number."; continue;;

Ancak ikinci kez, forkendisi dış whiledöngü içine yuvalanmış bir iç döngü içinde . Herhangi bir continueargüman kullanmazsam, bu continue 1dış fordöngü yerine iç döngüye eşdeğer olur ve devam eder while.

        ((REPLY <= cutoffs[$letter])) && { echo $letter; continue 2; }

Bu durumda continue 2bash'ı bulup ikinci döngüyü devam ettirmek için kullanıyorum.

Açıklama: caseGlobs ile Etiketler

Bir casesayının hangi harf notu bölmesine girdiğini ( AB'nin bash cevabında olduğu gibi ) bulmak için kullanmıyorum . Ancak case, kullanıcının girdisinin dikkate alınması gerekip gerekmediğine karar vermek için kullanıyorum :

  • geçerli bir sayı, *( )@([1-9]*([0-9])|+(0))*( )
  • quit komutu, *( )[qQ]?([uU][iI][tT])*( )
  • başka herhangi bir şey (ve dolayısıyla geçersiz girdi), *

Bunlar kabuklu küreler .

  • Her )birini (, casebir desen eşleştirildiğinde çalıştırılan komutlardan ayırmak için sözdizimi olan herhangi bir açıklıkla eşleşmeyen bir harf gelir.
  • ;;, casebir patiküler büyük / küçük harf eşleşmesi için çalıştırılacak komutların sonunu gösteren sözdizimidir (ve daha sonraki hiçbir durum çalıştırıldıktan sonra test edilmemelidir).

Sıradan kabuk globbing, *sıfır veya daha fazla karakteri, ?tam olarak bir karakteri ve karakter sınıflarını / aralıklarını [ ]parantez içinde eşleştirmeyi sağlar . Ama bunun ötesine geçen genişletilmiş bir globbing kullanıyorum . Genişletilmiş globbing, bashetkileşimli kullanılırken varsayılan olarak etkindir , ancak komut dosyası çalıştırıldığında varsayılan olarak devre dışıdır. shopt -s extglobScript üstündeki komut onu açıyor.

Açıklama: Genişletilmiş Globbing

*( )@([1-9]*([0-9])|+(0))*( ), sayısal girişi kontrol eden bir dizi ile eşleşir:

  • Sıfır veya daha fazla boşluk ( *( )). *( )Yapı maçları sıfır ya da sadece bir alandır burada parantez içinde desen, daha.
    Aslında iki tür yatay boşluk, boşluk ve sekme vardır ve genellikle sekmeleri de eşleştirmek istenir. Ama bu konuda endişelenmiyorum, çünkü bu komut dosyası manuel, etkileşimli giriş ve GNU okuma çizgisini etkinleştirmek için -ebayrak için yazılmıştır read. Bu, kullanıcının sol ve sağ ok tuşlarıyla metninde ileri ve geri hareket edebilmesidir, ancak genellikle sekmelerin tam olarak girilmesini önlemenin yan etkisi vardır.
  • Herhangi bir ( @( )) öğesinin bir örneği ( |):
    • Sıfır olmayan bir basamak ( [1-9]) ve ardından *( )herhangi bir basamaktan ( [0-9]) sıfır veya daha fazla ( ).
    • Bir veya daha fazla ( +( )) / 0.
  • Sıfır veya daha fazla boşluk ( *( )).

*( )[qQ]?([uU][iI][tT])*( ), quit komutunu kontrol eden bir dizi ile eşleşir:

  • Sıfır veya daha fazla boşluk ( *( )).
  • qveya Q( [qQ]).
  • İsteğe bağlı olarak - yani, sıfır veya bir tekrarlama ( ?( )) -:
    • uveya U( [uU]) ardından iveya I( [iI]) ardından tveya T( [tT]).
  • Sıfır veya daha fazla boşluk ( *( )).

Değişken: Girdiyi Genişletilmiş Düzenli İfadeyle Doğrulama

Kullanıcının girdisini kabuk glob yerine normal ifadeye karşı test etmeyi tercih ediyorsanız, aynı çalışan ancak genişletilmiş globbing yerine [[ve =~( terdon cevabında olduğu gibi) kullanan bu sürümü kullanmayı tercih edebilirsiniz case.

#!/usr/bin/env bash
shopt -s nocasematch

declare -A cutoffs
cutoffs[F]=59 cutoffs[D]=69 cutoffs[C]=79 cutoffs[B]=89 cutoffs[A]=100

while read -erp 'Enter numeric grade (q to quit): '; do
    # allow leading/trailing spaces, but not octal (e.g., "03")
    if [[ ! $REPLY =~ ^\ *([1-9][0-9]*|0+)\ *$ ]]; then
        [[ $REPLY =~ ^\ *q(uit)?\ *$ ]] && exit
        echo "I don't understand that number."; continue
    fi

    for letter in F D C B A; do
        ((REPLY <= cutoffs[$letter])) && { echo $letter; continue 2; }
    done
    echo "Grade out of range."
done

Bu yaklaşımın olası avantajları:

  • Bu özel durumda, sözdizimi biraz daha basittir, en azından ikinci desende, quit komutunu kontrol ediyorum. Ben ayarlamak başardı olmasıdır nocasematchkabuk seçeneği ve tüm dava ve varyantları qve quitotomatik kaplıydı.

    Yani ne shopt -s nocasematchkomut yok. shopt -s extglobKomut bu sürümde kullanılmaz globbing olarak kullanılmaz.

  • Düzenli ifade becerileri bash'ın uzatmalarında yeterlilikten daha yaygındır.

Açıklama: Normal İfadeler

=~Operatörün sağında belirtilen kalıplara gelince , bu düzenli ifadeler nasıl çalışır.

^\ *([1-9][0-9]*|0+)\ *$, sayısal girişi kontrol eden bir dizi ile eşleşir:

  • Çizginin ( ^) sol kenarı - başlangıcı .
  • Sıfır veya daha fazla ( *, uygulanan postfix) boşluk. Bir boşluğun \normal ifadede kaçması gerekmez , ancak [[sözdizimi hatasını önlemek için buna ihtiyaç vardır .
  • Aşağıdakilerden ( )biri veya diğeri ( |) olan bir alt dize ( ) :
    • [1-9][0-9]*: sıfır olmayan bir rakam ( [1-9]) ve ardından *herhangi bir rakamın ( [0-9]) sıfır veya daha fazla ( , postfix uygulandı ).
    • 0+: bir veya daha fazla ( +, uygulanan postfix) 0.
  • Daha \ *önce olduğu gibi sıfır veya daha fazla boşluk ( ).
  • Çizginin sonu ( $) , sağ kenarı - ( ).

caseTest edilen tüm ifadeyle eşleşen etiketlerin aksine =~, sol ifadesinin herhangi bir kısmı sağ ifadesi olarak verilen desenle eşleşirse true değerini döndürür. Bu nedenle, satırın başlangıcını ve sonunu belirten ^ve $çapalarına ihtiyaç vardır ve yöntemde caseve extglobs ile görünen herhangi bir şeye sözdizimsel olarak karşılık gelmez.

Parantez yapmak için gerekli olan ^ve $bir ayrılmalara bağlama [1-9][0-9]*ve 0+. Aksi takdirde bir ayrılma olur ^[1-9][0-9]*ve 0+$ve sıfır olmayan bir rakam ile başlayan herhangi bir giriş eşleşen ya da bir ile biten 0(ya da halen arasında olmayan basamak içerebilir bunların her ikisi de,).

^\ *q(uit)?\ *$, quit komutunu kontrol eden bir dizi ile eşleşir:

  • Satırın başlangıcı ( ^).
  • Sıfır veya daha fazla boşluk ( \ *yukarıdaki açıklamaya bakınız).
  • Mektup q. Veya Q, shopt nocasematchetkinleştirildiğinden beri .
  • İsteğe bağlı olarak - ?alt dizenin ( ( )) sıfır veya bir örneği (düzeltme ) - :
    • u, ardından i, ardından t. Veya shopt nocasematchetkin uolduğundan U; bağımsız olarak, iolabilir I; ve bağımsız olarak tolabilir T. (Yani, olasılıklar ve ile sınırlı değildir .)uitUIT
  • Sıfır veya daha fazla boşluk ( \ *).
  • Satırın sonu ( $).

3
Bana gerçeği söyle ... ne kadar zaman aldı? ;)
heemayl

4
@heemayl Gün boyunca birçok küçük parçaya yazdığımdan emin değilim (bunu göndermeden hemen önce tam bir okuma ve düzenlemeler takip eder). Eminim, ne kadar süreceğini düşünürsem, başladığımda düşündüğümden daha uzun sürdü. :)
Eliah Kagan

6
daha fazla yaz, cevaplarının bir kitabına ihtiyacım var.
Grijesh Chauhan

TL; DR ama yine de beni güldürdü!
Fabby

başlıktan açıklamaya kadar her şey iyidir. Ben ilk gitmek anladım ama ben sadece çünkü tekrar tekrar okudum
Sumeet Deshmukh

23

Temel fikre zaten sahipsiniz. Bunu kodlamak istiyorsanız bash(Ubuntu ve diğer birçok Linux'ta varsayılan kabuk olduğu için makul bir seçimdir), casearalıkları anlamadığı için kullanamazsınız . Bunun yerine if/ kullanabilirsiniz else:

#!/usr/bin/env bash

read -p "Please enter your choice: " response

## If the response given did not consist entirely of digits
if [[ ! $response =~ ^[0-9]*$ ]]
then
    ## If it was Quit or quit, exit
    [[ $response =~ [Qq]uit ]] && exit
    ## If it wasn't quit or Quit but wasn't a number either,
    ## print an error message and quit.
    echo "Please enter a number between 0 and 100 or \"quit\" to exit" && exit
fi
## Process the other choices
if [ $response -le 59 ]
then
    echo "F"
elif [ $response -le 69 ]
then
    echo "D"
elif  [ $response -le 79 ]
then
    echo "C"
elif  [ $response -le 89 ]
then
    echo "B"
elif [ $response -le 100 ]
then
    echo "A"
elif [ $response -gt 100 ]
then
    echo "Please enter a number between 0 and 100"
     exit
fi

4
Bu -getestlerin bir kısmı, kullandığınızdan, muhtemelen ortadan kaldırılabilir elif. Ve aşk yok (( $response < X ))mu?
muru

2
@muru true, teşekkürler. Sayı aralıklarında düşünmeye takılı kaldım ama bunun için bir neden yoktu. Gelince (( $response < X )), tabii, ama bu daha net bulmak ve OP Bash komut dosyası besbelli yenidir.
terdon

12
#!/bin/bash

while true
do
  read -p "Please enter your choice: " choice

  case "$choice"
   in
      [0-9]|[1-5][0-9])
          echo "F"
          ;;
      6[0-9])
          echo "D"
          ;;
      7[0-9])
          echo "C"
          ;;
      8[0-9])
          echo "B"
          ;;
      9[0-9]|100)
          echo "A"
          ;;
      [Qq])
          exit 0
          ;;
      *) echo "Only numbers between 0..100, q for quit"
          ;;
  esac
done

ve daha kompakt bir sürüm (Thx @EliahKagan ):

#!/usr/bin/env bash

while read -erp 'Enter numeric grade (q to quit): '; do
    case $REPLY in
        [0-9]|[1-5][0-9])   echo F ;;
        6[0-9])             echo D ;;
        7[0-9])             echo C ;;
        8[0-9])             echo B ;;
        9[0-9]|100)         echo A ;;

        [Qq])               exit ;;
        *)                  echo 'Only numbers between 0..100, q for quit' ;;
    esac
done

1
Bunlar kesinlikle karakter aralıkları mı? yani [0-59]0,1,2,3,4,5 veya 9'dan herhangi bir karakter anlamına gelir. Bunun sayısal değerler için nasıl çalıştığını göremiyorum .
steeldriver

3
Her zaman FGITW olmak zorunda değilsiniz. Size zaman ayırın, iyi cevaplar yazın. Terdon veya Eliah Kagan'ın nasıl çalıştığına bakın.
muru

@AB Bu çözümün çoğunlukla üslupsal değişikliklerle kısaltılabileceğini ve yine de oldukça okunabilir kaldığını fark ettim. Ben değilim bu yüzden Brevity nadiren en önemli husustur yok sen bu şekilde ne var değiştirmek gerektiğini düşünüyorum. Ancak daha kompakt form çok yer kaplamadığından, bazı okuyucuların aynı şekilde çalışan daha kısa bir komut dosyası istemesi durumunda da bunu göstermeyi düşünebilirsiniz. (İsterseniz, lütfen kısaltılmış versiyonumu veya herhangi bir varyasyonunu kullanmaktan çekinmeyin.)
Eliah Kagan

9

Tüm Ubuntu kurulumlarında Python var, bu yüzden bir python betiği bir astar. Eğer bash olması gerekiyorsa, ben de eşdeğer bir kabuk komut dosyası olarak yazdım .

print (chr(75-max(5,int('0'+raw_input('Enter the number: ')[:-1]))))

Çalıştırmak için bir dosyaya kaydedin (örn. grade.py) Ve ardından bununla terminalde çalıştırın:

python grade.py

Göreceğiniz şey bu:

Enter the number: 65
E

Bu nasıl çalışıyor?

  1. Girdi al - 65.
  2. Başına 0 ekleyin - 065.
  3. Son karakteri kaldırın - 06.
  4. Bu sayıyı çıkart 70.
  5. Bir harfe dönüştür (A 65, B 66) - E.
  6. Yazdırın E.

Benim zamirlerim O


Fikrini beğendim. +1
AB

Kullanmayın input()çağıracağı, eval()kullanın raw_input()sizin tesviye instead..also doğru olarak değil 90+sınıf yazdırır B..use chr(74 - max(4, num))....
heemayl

well..your çözüm güzel ve değişim also..just python2 çalışacak input()için raw_input()python2..thats için ..
heemayl

print chr(75-max(5,int('0'+raw_input('Enter the number: ')[:-1])))
heemayl

Sonra o anda sanki yanlıştır haliyle orijinal kod too..your kodunu modifed değiştirmenize gerek python3yok raw_input()ben önerdi .. raw_input()kullandığınız çalıştırmak için söylediğim gibi başlangıçtaki biri için python2..
heemayl

6

İşte 101 girişli bir diziyi dolduran ve daha sonra kullanıcı girişini bunlara karşı kontrol eden yarı- ezoterik bash çözümüm. Gerçek dünya kullanımı için bile makul - mükemmel performansa ihtiyacınız varsa bash kullanmazsınız ve yüz (ya da öylesine) ödev hala hızlıdır. Ancak, daha geniş bir aralığa (bir milyon gibi) genişletilirse makul olmayı bırakacaktır.

#!/usr/bin/env bash
p(){ for i in `seq $2 $3`; do g[$i]=$1; done; }
p A 90 100; p B 80 89; p C 70 79; p D 60 69; p F 0 59
while read -r n && [[ ! $n =~ ^[qQ] ]]; do echo ${g[$n]}; done

Avantajları:

  • Gerçekten o kadar ezoterik değil. En kısa çözümlerden daha uzun olmasına ve daha uzun çözümler kadar kendi kendini belgelemesine rağmen ... makul bir şekilde kendi kendini belgelemekle birlikte , yine de kesinlikle küçük tarafta.
  • Not aralıklarını değiştirmek veya not eklemek / çıkarmak için kolay modifikasyon sağlar.
  • Bu bir döngü ve kapanıyor faaliyet q, quitya da hiçbir şey ile başlayan q/ ' Q.
  • Olumlu düşünmenize yardımcı olmak için önce daha yüksek notları listeler. :)
  • Hmm, bu işi yapıyor, baktıktan sonra bile mantıklı duruyor ve gerekli özelliklere sahip. Bunu gerçekten kullanabilirsiniz!

Dezavantajları:

  • Sayısal olmayan bir girdi girdiğinizde size bir F verir ... ama bu o kadar da kötü değil, değil mi? Bir numaranın gerekli olduğu yerde bir sayı olmayan bir sayı verirseniz, belki bir F!
  • Belirsiz, muhtemelen sekizli girdi sekizli olarak ele alınır (çünkü tek boyutlu dizine alınmış gbir dizidir ). Eski deyiş, "Bu bir hata değil, bir özellik!" Pekala belki.
  • Aralık dışında olan veya sayı olmayan girişler boş bir satırın yazdırılmasına neden oluyor. Bununla ilgili gerçekten yanlış bir şey yok: bu, girişinize hangi harf notunun karşılık geldiğini söyler ve yanlış giriş için biri yoktur.
  • Negatif bir sayı girin ve buna ... Paskalya yumurtası deyin .
  • Hala Tim'in python çözümünden önemli ölçüde daha uzun . Evet, bunu gerçekten bir avantaj gibi göremiyorum.

Çok havalı, ha? (Bence de öyle.)

Nasıl çalışır

  1. pFonksiyon s sayısal olarak endeksli bir dizi opulates garasında gr üçüncü argümanındaki (letter) değeri ile ikinci ilk argüman arasında değişen dizinler rades,.
  2. p her harf notu için sayısal aralığını tanımlamak üzere çağrılır.
  3. Kullanılabilir olduğu sürece q(veya Q) ile başlamadığı , gharf notunun girilen sayıya karşılık gelen diziyi kontrol ettiği ve o harfi yazdığı sürece kullanıcı girişini okumaya devam edin .

Bu şartlı durum ne olacak? [[ $n =~ ^(0|[1-9]+[0-9]*)$ ]]
Helio

6

Python 2'de yaptıktan sonra bash yapmaya karar verdim.

#! /bin/bash

read -p "Enter the number: " i
i=0$i
x=$((10#${i::-1}))
printf "\x$(printf %x $((11-($x>5?$x:5)+64)))\n"

Çalıştırmak için dosyayı bir dosyaya kaydedin (örn. Grade.sh), ile chmod +x grade.shçalıştırılabilir yapın ve ardından ile çalıştırın ./grade.sh.

Göreceğiniz şey bu:

Enter the number: 65
E

Bu nasıl çalışıyor?

  1. Girdi al - 65.
  2. Başına bir 0 ekleyin - 065(ve 10#temelini 10 tutar).
  3. Son karakteri kaldırın - 06.
  4. Bu sayıyı çıkart 70.
  5. Bir harfe dönüştür (A 65, B 66) - E.
  6. Yazdırın - E.

Benim zamirlerim O


Çok zeki, aferin
kos

@kos teşekkürler :) OP için çalışacağından şüpheliyim çünkü aralıkları muhtemelen yayınladığı şey değil. Bunların basitlik için olduğunu düşünüyorum.
Tim

5

Ve işte benim awk versiyonu:

awk '{
  if($_ <= 100 && $_ >= 0) {
      sub(/^([0-9]|[1-5][0-9])$/, "F", $_);
      sub(/^(6[0-9])$/, "D", $_);
      sub(/^(7[0-9])$/, "C", $_);
      sub(/^(8[0-9])$/, "B", $_);
      sub(/^(9[0-9]|100)$/, "A", $_);
      print
    }
    else {
      print "Only numbers between 0..100"
    }
}' -

veya tek astar olarak:

awk '{if($_ <= 100 && $_ >= 0) { sub(/^([0-9]|[1-5][0-9])$/, "F", $_); sub(/^(6[0-9])$/, "D", $_); sub(/^(7[0-9])$/, "C", $_); sub(/^(8[0-9])$/, "B", $_);sub(/^(9[0-9]|100)$/, "A", $_);   print} else { print "Only numbers between 0..100"}}' -

4

İşte başka bir "ezoterik" cevap

perl -E '
    print "number: "; 
    $n = <>; 
    say qw/A A B C D E F F F F F/[11-($n+1)/10]
       if $n=~/^\s*\d/ and 0<=$n and $n<=100
'

açıklama

  • perl -E: the -E, like -e, bir komut dosyasını komut satırı argümanı olarak geçirmeye izin verir. Bu perl tek gömlekleri çalıştırmak için bir yoldur. Bunun aksine -e, -Etüm isteğe bağlı özellikleri de etkinleştirir ( saytemelde printsondaki bir yeni satır olan bir.).
  • print "number: "; : kullanıcıdan bir numara girmesini ister.
  • $n = <>;: bu numarayı kaydedin $n.

Bir sonraki bitin biraz parçalanması gerekiyor. boşlukta qw/string/kırılarak yapılan bir listeyi değerlendirir string. Yani, qw/A A B C D E F F F F F/aslında bu liste:

0 : A
1 : A
2 : B
3 : C
4 : D
5 : E
6 : F
7 : F
8 : F
9 : F
10 : F

Bu nedenle, say qw/A A B C D E F F F F F/[11-($n+1)/10]eşdeğerdir

my @F=("A","A","B","C","D","E","F","F","F","F","F");
print "$F[11-($n+1)/10]\n"

Şimdi Perl, dizinin sonundan sayılan öğeleri almak için negatif indekslerin kullanılmasına izin veriyor. Örneğin,$arrray[-1] , dizinin son öğesini yazdırır. Ayrıca, kayan nokta dizisi indeksleri (örneğin 10.7) otomatik olarak bir sonraki düşük tam sayıya (10.7 veya 10.3 veya 10 olursa olsun) otomatik olarak kesilir.)

Tüm bunların sonucu, dizinin 11-($n+1)/10daima dizinin ilgili öğesine (derecesine) göre değerlendirilmesidir.


4
Ezoterik cevapların hepsi güzel, ancak lütfen bir açıklama ekleyin.
muru

1

Her ne kadar bash bir çözüm isteseniz de, python'da, bu zarif bir şekilde kısa bir şekilde yapılabilir. Yanlış giriş durumunda her iki kullanım hatasını ve 0 ile 100 arasında bir sayının "dönüşümünü" A'dan F'ye (veya başka bir harflere) dönüştürmek:

#!/usr/bin/env python3
try:
    n = int(input("number: ")); n = n if n>0 else ""
    print("FEDCBA"[[n>=f for f in [50,60,70,80,90,101]].count(True)])
except:
    print("invalid input")

açıklama

  1. Öncelikle numarayı kullanıcıdan almamız gerekiyor:

    n = int(input("number: "))
  2. Bu sayıyı birkaç koşul için geçerli olarak test ediyoruz:

    n>=50, n>=60, n>=70, n>=80, n>=90

    Bu testlerin her biri için sonuç ya Falseya olacaktır True. Bu nedenle (kodu biraz sıkıştırmak):

    [n>=f for f in [50,60,70,80,90]].count(True)]

    bir şekil üretecektir 0için5

  3. Daha sonra, bu şekli çıktı olarak bir karakter üretmek için bir dize dizini olarak kullanabiliriz , ör.

    "ABCDEF"[3] 

    "D" çıktısı alır (ilk karakter = "A" olduğundan)

  4. Ek 101listesine sayısı aşması durumunda, bir (SSR) hata oluşturmak için 100, çünkü "ABCDEF"[6]mevcut değildir. n = n if n>=0 else ""Aynısı geçerlidir , bu da 0'ın altında bir sayı girilirse (Değer-) hatası oluşturur
    Bu durumlarda ve giriş bir rakam değilse, sonuç şöyle olur:

    invalid input

Testler:

number: 10
F

number: 50
E

number: 60
D

number: 70
C

number: 80
B

number: 90
A

number: 110
invalid input

number: -10
invalid input

number: Monkey
invalid input
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.