Điều gì sẽ là cách tốt nhất để kiểm tra xem $ 1 có phải là số nguyên trong / bin / dash không?
Trong bash, tôi có thể làm:
[[ $1 =~ ^([0-9]+)$ ]]
Nhưng điều đó dường như không tuân thủ POSIX và dấu gạch ngang không hỗ trợ điều đó
Điều gì sẽ là cách tốt nhất để kiểm tra xem $ 1 có phải là số nguyên trong / bin / dash không?
Trong bash, tôi có thể làm:
[[ $1 =~ ^([0-9]+)$ ]]
Nhưng điều đó dường như không tuân thủ POSIX và dấu gạch ngang không hỗ trợ điều đó
Câu trả lời:
Sau đây phát hiện các số nguyên, tích cực hoặc tiêu cực, và hoạt động theo dash
và là POSIX:
echo "$1" | grep -Eq '^[+-]?[0-9]+$' && echo "It's an integer"
case "${1#[+-]}" in
''|*[!0-9]*)
echo "Not an integer" ;;
*)
echo "Integer" ;;
esac
Hoặc, với một chút sử dụng lệnh :
(nop):
! case ${1#[+-]} in *[!0-9]*) :;; ?*) ! :;; esac && echo Integer
Cho dù dash
, bash
, ksh
, zsh
, POSIX sh
, hoặc posh
( "một reimplementation của Bourne shell" sh
); các case
cấu trúc là nhất phổ biến rộng rãi và đáng tin cậy:
case $1 in (*[!0-9]*|"") false ;; (*) true ;; esac
dash
? Nó làm việc cho tôi dưới bash
nhưng không dash
.
dash
; để thẩm vấn kết quả tôi đã thêm echo $?
sau lệnh case.
posh
("một sự tái hiện của vỏ Bourne") cũng không có vấn đề gì với giải pháp đó.
case
; Một lý do là lỗi bạn mô tả, một lý do khác trong các trình soạn thảo có các tính năng dựa trên dấu ngoặc đơn phù hợp (vim), nó mang lại sự hỗ trợ tốt hơn nhiều, và không ít nhất tôi thấy nó phù hợp hơn với cá nhân. - WRT posh
là POSIX; tốt, trích dẫn từ trang người đàn ông mà tôi đã đề xuất một cái gì đó khác, nhưng tôi đoán không thể dựa vào những tuyên bố không chính thức như vậy. Vỏ bourne cũ dù sao cũng không còn quan trọng nữa khi chúng ta đang ở kỷ nguyên POSIX.
Bạn có thể sử dụng -eq
thử nghiệm trên chuỗi, với chính nó:
$ 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
Nếu thông báo lỗi là một vấn đề, hãy chuyển hướng đầu ra lỗi sang /dev/null
:
$ dash -c 'a="0xa"; [ "$a" -eq "$a" ] 2>/dev/null|| echo no'
no
" 023 "
là một con số. Lưu ý rằng nó hoạt động với dấu gạch ngang, nhưng không phải tất cả các vỏ POSIX khác vì hành vi không được chỉ định nếu các toán hạng là số nguyên thập phân ghi chú. Ví dụ với ksh, nó sẽ nói rằng SHLVL
hoặc 1+1
là một số.
Hãy thử sử dụng nó như một mở rộng số học, và xem nếu nó hoạt động. Trên thực tế, bạn cần phải nghiêm ngặt hơn một chút, bởi vì việc mở rộng số học sẽ bỏ qua các không gian hàng đầu và dấu, chẳng hạn. Vì vậy, thực hiện mở rộng số học và đảm bảo rằng kết quả mở rộng khớp chính xác với biến ban đầu.
check_if_number()
{
if [ "$1" = "$((${1}))" ] 2>/dev/null; then
echo "Number!"
else
echo "not a number"
fi
}
Điều này cũng sẽ chấp nhận số âm - nếu bạn thực sự muốn loại trừ chúng, hãy thêm một kiểm tra bổ sung cho $((${1} >= 0))
.
[[
$(( ... ))
không? Nếu vậy, câu trả lời của tôi vẫn phải chính xác về mặt vật chất, tôi chỉ cần thêm một số trích dẫn thêm.
check_if_number 1.2
và chức năng trả về: dash: 3: arithmetic expression: expecting EOF: "1.2"
Có lẽ với expr
?
if expr match "$1" '^\([0-9]\+\)$' > /dev/null; then
echo "integer"
else
echo "non-integer"
fi
match
phải \+
là POSIX. Nó cũng sẽ nói 0 không phải là một số. Bạn muốnexpr "x$1" : 'x[0-9]\{1,\}$'
Trong hệ thống POSIX, bạn có thể sử dụng expr :
$ a=a
$ expr "$a" - 0 >/dev/null 2>&1
$ [ "$?" -lt 2 ] && echo Integer || echo Not Integer
expr
triển khai sẽ nói rằng 9999999999999999999 không phải là số nguyên. POSIX không bảo đảm rằng nó sẽ hoạt động. Trong thực tế, trên một hệ thống GNU ít nhất, nó sẽ nói rằng "độ dài" là một số nguyên.
expr 9999999999999999999 + 0
cho tôi trạng thái thoát 3 expr -12 + 0
và expr length + 0
cho tôi trạng thái thoát 0 với GNU expr ( + string
các lực string
được coi là một chuỗi với GNU expr
. expr "$a" - 0
Sẽ hoạt động tốt hơn).
-12
là một số nguyên hợp lệ, và 9999999999999999999
đã tràn.
Đây là một hàm đơn giản sử dụng cùng một phương thức như câu trả lời của muru :
IsInteger() # usage: IsInteger string
{ # returns: flag
[ "$1" -eq "$1" ] 2> /dev/null
}
Thí dụ:
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"
Đầu ra:
'2a3' isn't an integer
'23' is an integer
foo\n123\nbar
không phải là một số nguyên, nhưng sẽ vượt qua bài kiểm tra này.