อะไรจะเป็นวิธีที่ดีที่สุดในการตรวจสอบว่า $ 1 เป็นจำนวนเต็มใน / bin / dash หรือไม่
ในทุบตีฉันสามารถทำ:
[[ $1 =~ ^([0-9]+)$ ]]
แต่ดูเหมือนจะไม่เป็นไปตาม POSIX และ dash ไม่สนับสนุนสิ่งนั้น
อะไรจะเป็นวิธีที่ดีที่สุดในการตรวจสอบว่า $ 1 เป็นจำนวนเต็มใน / bin / dash หรือไม่
ในทุบตีฉันสามารถทำ:
[[ $1 =~ ^([0-9]+)$ ]]
แต่ดูเหมือนจะไม่เป็นไปตาม POSIX และ dash ไม่สนับสนุนสิ่งนั้น
คำตอบ:
ตรวจจับจำนวนเต็มบวกหรือลบและทำงานภายใต้dash
และเป็น POSIX ต่อไปนี้:
echo "$1" | grep -Eq '^[+-]?[0-9]+$' && echo "It's an integer"
case "${1#[+-]}" in
''|*[!0-9]*)
echo "Not an integer" ;;
*)
echo "Integer" ;;
esac
หรือด้วยการใช้:
คำสั่ง (nop) เล็กน้อย:
! case ${1#[+-]} in *[!0-9]*) :;; ?*) ! :;; esac && echo Integer
ไม่ว่าจะเป็นdash
, bash
, ksh
, zsh
, POSIX sh
หรือposh
( "a reimplementation ของบอร์นเชลล์" sh
); การcase
ก่อสร้างนั้นมีอยู่อย่างกว้างขวางและเชื่อถือได้มากที่สุด:
case $1 in (*[!0-9]*|"") false ;; (*) true ;; esac
dash
หรือไม่? การทำงานสำหรับฉันภายใต้แต่ไม่bash
dash
dash
เช่นกัน เพื่อสอบถามผลลัพธ์ที่ฉันเพิ่มecho $?
หลังจากคำสั่ง case
posh
("การใช้งานใหม่ของบอร์นเชลล์") ก็ไม่มีปัญหาในการแก้ปัญหาดังกล่าว
case
; เหตุผลข้อหนึ่งคือข้อผิดพลาดที่คุณอธิบายอีกข้อหนึ่งที่ในโปรแกรมแก้ไขที่มีคุณสมบัติที่ต้องพึ่งพาวงเล็บที่ตรงกัน (vim) จะให้การสนับสนุนที่ดีกว่ามาก - WRT posh
เป็น POSIX; ดีอ้างจากหน้าคนที่ฉันให้คำแนะนำอย่างอื่น แต่อย่างใดอย่างหนึ่งไม่สามารถพึ่งพางบนอกระบบดังกล่าวฉันเดา เชลล์ bourne เก่านั้นไม่สำคัญเท่าไรตอนนี้เราอยู่ในยุค POSIX
คุณสามารถใช้การ-eq
ทดสอบกับสตริงด้วยตัวเอง:
$ 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
หากข้อความแสดงข้อผิดพลาดเป็นปัญหาให้เปลี่ยนเส้นทางข้อผิดพลาดไปที่/dev/null
:
$ dash -c 'a="0xa"; [ "$a" -eq "$a" ] 2>/dev/null|| echo no'
no
" 023 "
เป็นตัวเลข โปรดทราบว่ามันทำงานร่วมกับประ แต่ไม่ใช่เปลือก POSIX อื่น ๆ ทั้งหมดเป็นพฤติกรรมที่ไม่ได้ระบุหากตัวถูกดำเนินการเป็นจำนวนเต็มทศนิยมทศนิยม เช่นกับ ksh มันจะบอกว่าSHLVL
หรือ1+1
เป็นตัวเลข
ลองใช้เป็นส่วนขยายเลขคณิตและดูว่าใช้งานได้หรือไม่ ที่จริงแล้วคุณต้องเข้มงวดกว่านั้นเล็กน้อยเนื่องจากการขยายเลขคณิตจะไม่สนใจช่องว่างนำหน้าและส่วนท้าย ดังนั้นการขยายเลขคณิตและตรวจสอบให้แน่ใจว่าผลลัพธ์ที่ขยายเพิ่มนั้นตรงกับตัวแปรดั้งเดิมอย่างแน่นอน
check_if_number()
{
if [ "$1" = "$((${1}))" ] 2>/dev/null; then
echo "Number!"
else
echo "not a number"
fi
}
นอกจากนี้ยังจะยอมรับตัวเลขติดลบ - $((${1} >= 0))
ถ้าคุณจริงๆหมายถึงจะไม่รวมพวกเขาเพิ่มการตรวจสอบพิเศษสำหรับ
[[
$(( ... ))
หรือไม่ ถ้าเป็นเช่นนั้นคำตอบของฉันยังควรถูกต้องอย่างมีนัยสำคัญฉันต้องเพิ่มข้อความพิเศษ
check_if_number 1.2
และฟังก์ชั่นคืน: dash: 3: arithmetic expression: expecting EOF: "1.2"
อาจจะด้วยexpr
?
if expr match "$1" '^\([0-9]\+\)$' > /dev/null; then
echo "integer"
else
echo "non-integer"
fi
match
มิได้\+
มี POSIX มันก็จะบอกว่า 0 ไม่ใช่ตัวเลข คุณต้องการexpr "x$1" : 'x[0-9]\{1,\}$'
ในระบบ POSIX คุณสามารถใช้expr :
$ a=a
$ expr "$a" - 0 >/dev/null 2>&1
$ [ "$?" -lt 2 ] && echo Integer || echo Not Integer
expr
การใช้งานบางอย่างจะบอกว่า 9999999999999999999 ไม่ใช่จำนวนเต็ม POSIX ไม่รับประกันว่าจะใช้งานได้ ในทางปฏิบัติในระบบ GNU เป็นอย่างน้อยมันจะบอกว่า "length" เป็นจำนวนเต็ม
expr 9999999999999999999 + 0
ให้ฉันสถานะ 3 และทางออกexpr -12 + 0
และexpr length + 0
ให้ฉันสถานะ 0 ทางออกกับ GNU expr ( + string
กองกำลังstring
ที่จะได้รับการพิจารณาเป็นสตริงกับ GNU expr
. expr "$a" - 0
จะทำงานได้ดี)
-12
เป็นจำนวนเต็มที่ถูกต้องและ9999999999999999999
ให้มากเกินไป
นี่เป็นฟังก์ชั่นเรียบง่ายโดยใช้วิธีการเดียวกับคำตอบของmuru :
IsInteger() # usage: IsInteger string
{ # returns: flag
[ "$1" -eq "$1" ] 2> /dev/null
}
ตัวอย่าง:
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"
เอาท์พุท:
'2a3' isn't an integer
'23' is an integer
foo\n123\nbar
ไม่ใช่จำนวนเต็ม แต่จะผ่านการทดสอบนี้