/ bin / dash: 1 TL'nin bir sayı olup olmadığını kontrol et


12

$ 1 öğesinin / bin / dash içinde bir tam sayı olup olmadığını kontrol etmenin en iyi yolu nedir?

Bash'da şunları yapabilirim:

[[ $1 =~ ^([0-9]+)$ ]]

Ancak bu POSIX uyumlu görünmüyor ve tire bunu desteklemiyor

Yanıtlar:


12

Aşağıdaki, pozitif veya negatif tamsayıları algılar dashve POSIX altında çalışır :

seçenek 1

echo "$1" | grep -Eq '^[+-]?[0-9]+$' && echo "It's an integer"

seçenek 2

case "${1#[+-]}" in
    ''|*[!0-9]*)
        echo "Not an integer" ;;
    *)
        echo "Integer" ;;
esac

Veya :(nop) komutunu biraz kullanarak :

! case ${1#[+-]} in *[!0-9]*) :;; ?*) ! :;; esac && echo Integer

5
Dize yeni satır içeriyorsa ne olur? foo\n123\nbartamsayı değildir, ancak bu testi geçecektir.
godlygeek

3
Grep versiyonu, yani. Olgu sürümü doğru görünüyor.
godlygeek

5

İster dash, bash, ksh, zsh, POSIX shveya posh( "Bourne kabuğunun bir reimplementation" sh ); caseyapı en yaygın kullanılan ve güvenilirdir:

case $1 in (*[!0-9]*|"") false ;; (*) true ;; esac

Bunu altında test ettin dashmi? Benim için çalışıyor bashama çalışmıyor dash.
John1024

Evet, bunu sistemimde de test ettim dash; echo $?case komutundan sonra eklediğim sonucu sorgulamak için .
Janis

Ben de aynısını yaptım (Debian ahır) ama sevinç yok. Kısa çizgimde benim için çalışan eksiksiz bir örnek için bkz . Seçenek 2 .
John1024

Hmm, test etmek için orijinal bourne kabuğum yok. "[Ksh] bourne kabuğu değil özellikleri" hakkında teftiş dokümanlar en azından söz değil, bu yüzden orada olduğunu varsayalım. Hayır? - Öyleyse önde gelen parantezi atlayın. - OTOH, posh("Bourne kabuğunun yeniden uygulanması") da bu çözümle ilgili bir sorun yaşamıyor.
Janis

1
@mikeserv; Her zaman eşleşen parantezleri kullanmamın birkaç nedeni vardır case; bir nedeni tanımladığınız hatadır, başka bir editörlerde, parantez (vim) ile eşleşen özelliklere sahip olan editörlerde çok daha iyi destek verir ve en azından kişisel olarak daha iyi okunabilir buluyorum. - WRT poshPOSIX; Eh, verdiğim adam sayfasından alıntı başka bir şey önerdi, ama sanırım, bu tür gayrı resmi ifadelere güvenemezsiniz. Eski bourne kabuğu artık POSIX çağında olduğumuz için o kadar da önemli değil.
Janis

1

Sen kullanabilirsiniz -eqkendisiyle, ipe testi:

$ dash -c 'a="a"; if [ "$a" -eq "$a" ] ; then echo number; else echo not a number; fi' 
dash: 1: [: Illegal number: a
not a number
$ dash -c 'a="0xa"; if [ "$a" -eq "$a" ] ; then echo number; else echo not a number; fi'
dash: 1: [: Illegal number: 0xa
not a number
$ dash -c 'a="-1"; if [ "$a" -eq "$a" ] ; then echo number; else echo not a number; fi'
number

Hata mesajı bir sorunsa, hata çıktısını şuraya yönlendirin /dev/null:

$ dash -c 'a="0xa"; [ "$a" -eq "$a" ] 2>/dev/null|| echo no'
no

1
Ayrıca bunun " 023 "bir sayı olduğunu söyleyebiliriz . İşlenenler ondalık tamsayılarsa davranış belirtilmediğinden, tire ile çalıştığını, ancak diğer tüm POSIX kabuklarını çalışmadığını unutmayın. Örneğin ksh ile, SHLVLya 1+1da bir sayı olduğunu söyleyebilir .
Stéphane Chazelas

0

Bir aritmetik genişletme olarak kullanmayı deneyin ve çalışıp çalışmadığına bakın. Aslında, bundan biraz daha katı olmanız gerekir, çünkü aritmetik açılımlar önde gelen ve arkadaki boşlukları görmezden gelir. Aritmetik bir genişleme yapın ve genişletilmiş sonucun orijinal değişkenle tam olarak eşleştiğinden emin olun.

check_if_number()
{
    if [ "$1" = "$((${1}))" ] 2>/dev/null; then
        echo "Number!"
    else
        echo "not a number"
    fi
}

Bu, negatif sayıları da kabul eder - eğer gerçekten hariç tutmak istiyorsanız, ekstra bir kontrol ekleyin $((${1} >= 0)).


1
dash yok[[
glenn jackman

@glennjackman Whoops. Var mı $(( ... ))? Eğer öyleyse, cevabım hala maddi olarak doğru olmalı, sadece ekstra alıntı eklemem gerekiyor.
godlygeek

bu senin cevabın: git öğren.
glenn jackman

Görünüşe göre, güncellenmiş sürümüm hile yapmalı. Yine de test etmek için bir çizgim yok - bu yüzden başka bir şey kaçırıp kaçırmadığımı bana bildirin.
godlygeek

Denedim: check_if_number 1.2ve fonksiyon döndü: dash: 3: arithmetic expression: expecting EOF: "1.2"
John1024

0

Belki ile expr?

if expr match "$1" '^\([0-9]\+\)$' > /dev/null; then
  echo "integer"
else 
  echo "non-integer"
fi

POSIX de matchne \+. Ayrıca 0'ın bir sayı olmadığını söyleyebiliriz. Sen istiyorsunexpr "x$1" : 'x[0-9]\{1,\}$'
Stéphane Chazelas

0

POSIX sisteminde ifade kullanabilirsiniz :

$ a=a
$ expr "$a" - 0 >/dev/null 2>&1
$ [ "$?" -lt 2 ] && echo Integer || echo Not Integer

0'ın bir tamsayı olmadığını söyleyecektir (ve OP'nin bash çözümünün reddedeceği -12 diyelim). Bazı expruygulamalar 9999999999999999999'un bir tam sayı olmadığını söyleyecektir. POSIX bunun işe yarayacağına dair hiçbir garanti vermez. Uygulamada, en azından bir GNU sisteminde, "uzunluk" un bir tamsayı olduğunu söyleyecektir.
Stéphane Chazelas

Testimde en azından Debian ve OSX'te çalışıyor. 0 için tamsayı der. Posix $ a ifadesi aritmetik için geçerli bir ifade (tamsayı) olmalıdır.
cuonglm

Oh evet, üzgünüm, testinizi $ için göz ardı etmiş miydim? <2. Yine expr 9999999999999999999 + 0bana 3 çıkış durumu verir ve expr -12 + 0ve expr length + 0bana GNU expr ile 0 çıkış durumu vermek ( + stringkuvvetler stringGNU bir dize olarak dikkate alınması gereken expr. expr "$a" - 0Daha iyi çalışacak).
Stéphane Chazelas

@ StéphaneChazelas: Ah, evet, cevabımı güncelledim. Bence -12geçerli bir tamsayı ve 9999999999999999999bir taşma verdi.
cuonglm

0

İşte muru'nun cevabı ile aynı yöntemi kullanan basit bir fonksiyon :

IsInteger()      # usage: IsInteger string
{               #  returns: flag
        [ "$1" -eq "$1" ] 2> /dev/null
}

Misal:

p= n=2a3; IsInteger $n || p="n't" ; printf "'%s' is%s an integer\n" "$n" "$p"
p= n=23;  IsInteger $n || p="n't" ; printf "'%s' is%s an integer\n" "$n" "$p"

Çıktı:

'2a3' isn't an integer
'23' is an integer
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.