Apa cara terbaik untuk memeriksa apakah $ 1 adalah integer di / bin / dash?
Dalam bash, saya bisa melakukan:
[[ $1 =~ ^([0-9]+)$ ]]
Tapi itu tampaknya tidak sesuai dengan POSIX dan tanda hubung tidak mendukung itu
Apa cara terbaik untuk memeriksa apakah $ 1 adalah integer di / bin / dash?
Dalam bash, saya bisa melakukan:
[[ $1 =~ ^([0-9]+)$ ]]
Tapi itu tampaknya tidak sesuai dengan POSIX dan tanda hubung tidak mendukung itu
Jawaban:
Mendeteksi bilangan bulat berikut, positif atau negatif, dan bekerja di bawah dash
dan POSIX:
echo "$1" | grep -Eq '^[+-]?[0-9]+$' && echo "It's an integer"
case "${1#[+-]}" in
''|*[!0-9]*)
echo "Not an integer" ;;
*)
echo "Integer" ;;
esac
Atau, dengan sedikit menggunakan perintah :
(nop):
! case ${1#[+-]} in *[!0-9]*) :;; ?*) ! :;; esac && echo Integer
Entah dash
, bash
, ksh
, zsh
, POSIX sh
, atau posh
( "implementasi ulang dari Bourne shell" sh
); yang case
membangun adalah yang paling banyak tersedia dan dapat diandalkan:
case $1 in (*[!0-9]*|"") false ;; (*) true ;; esac
dash
? Ini bekerja untuk saya di bawah bash
tetapi tidak dash
.
dash
; untuk menginterogasi hasil yang saya tambahkan echo $?
setelah perintah kasus.
posh
("implementasi ulang shell Bourne") juga tidak memiliki masalah dengan solusi itu.
case
; salah satu alasannya adalah bug yang Anda jelaskan, satu lagi yang dalam editor yang memiliki fitur yang bergantung pada tanda kurung yang cocok (vim) memberikan dukungan yang lebih baik, dan paling tidak saya merasa secara pribadi lebih mudah dibaca untuk mencocokkannya. - WRT posh
menjadi POSIX; Yah, kutipan dari halaman manual yang saya berikan menyarankan sesuatu yang lain, tetapi orang tidak bisa mengandalkan pernyataan informal seperti itu, saya kira. Shell bourne lama tidak lagi signifikan sekarang karena kita berada di era POSIX.
Anda dapat menggunakan -eq
tes pada string, dengan sendirinya:
$ 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
Jika pesan kesalahan adalah masalah, redirect output kesalahan ke /dev/null
:
$ dash -c 'a="0xa"; [ "$a" -eq "$a" ] 2>/dev/null|| echo no'
no
" 023 "
angka. Perhatikan bahwa ia bekerja dengan tanda hubung, tetapi tidak semua shell POSIX lainnya karena perilakunya tidak ditentukan jika operannya adalah bilangan desimal. Misalnya dengan ksh, itu akan mengatakan itu SHLVL
atau 1+1
angka.
Coba gunakan itu sebagai ekspansi aritmatika, dan lihat apakah itu berfungsi. Sebenarnya, Anda harus sedikit lebih ketat dari itu, karena ekspansi aritmatika akan mengabaikan ruang depan dan belakang, misalnya. Jadi lakukan ekspansi aritmatika, dan pastikan bahwa hasil yang diperluas cocok dengan variabel asli dengan tepat.
check_if_number()
{
if [ "$1" = "$((${1}))" ] 2>/dev/null; then
echo "Number!"
else
echo "not a number"
fi
}
Ini juga akan menerima angka negatif - jika Anda bermaksud mengecualikannya, tambahkan cek tambahan untuk $((${1} >= 0))
.
[[
$(( ... ))
? Jika demikian, jawaban saya masih benar secara materi, saya hanya perlu menambahkan beberapa kutipan tambahan.
check_if_number 1.2
dan fungsinya kembali: dash: 3: arithmetic expression: expecting EOF: "1.2"
Mungkin dengan expr
?
if expr match "$1" '^\([0-9]\+\)$' > /dev/null; then
echo "integer"
else
echo "non-integer"
fi
match
juga \+
adalah POSIX. Itu juga akan mengatakan 0 bukan angka. Anda inginexpr "x$1" : 'x[0-9]\{1,\}$'
Dalam sistem POSIX, Anda dapat menggunakan expr :
$ a=a
$ expr "$a" - 0 >/dev/null 2>&1
$ [ "$?" -lt 2 ] && echo Integer || echo Not Integer
expr
implementasi akan mengatakan bahwa 999999999999999999999 bukan bilangan bulat. POSIX tidak memberikan jaminan bahwa ini akan berhasil. Dalam praktiknya, setidaknya pada sistem GNU, ia akan mengatakan bahwa "panjang" adalah bilangan bulat.
expr 9999999999999999999 + 0
memberi saya status keluar 3 dan expr -12 + 0
dan expr length + 0
memberi saya status keluar 0 dengan GNU expr ( + string
memaksa string
untuk dianggap sebagai string dengan GNU expr
. expr "$a" - 0
Akan bekerja lebih baik).
-12
adalah integer yang valid, dan 9999999999999999999
memberikan overflow.
Inilah fungsi sederhana menggunakan metode yang sama dengan jawaban muru :
IsInteger() # usage: IsInteger string
{ # returns: flag
[ "$1" -eq "$1" ] 2> /dev/null
}
Contoh:
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"
Keluaran:
'2a3' isn't an integer
'23' is an integer
foo\n123\nbar
bukan bilangan bulat, tetapi akan lulus tes ini.