¿Cuál sería la mejor manera de verificar si $ 1 es un entero en / bin / dash?
En bash, podría hacer:
[[ $1 =~ ^([0-9]+)$ ]]
Pero eso no parece ser compatible con POSIX y el guión no es compatible con eso
¿Cuál sería la mejor manera de verificar si $ 1 es un entero en / bin / dash?
En bash, podría hacer:
[[ $1 =~ ^([0-9]+)$ ]]
Pero eso no parece ser compatible con POSIX y el guión no es compatible con eso
Respuestas:
Los siguientes detectan enteros, positivos o negativos, y funcionan debajo dash
y son POSIX:
echo "$1" | grep -Eq '^[+-]?[0-9]+$' && echo "It's an integer"
case "${1#[+-]}" in
''|*[!0-9]*)
echo "Not an integer" ;;
*)
echo "Integer" ;;
esac
O, con un poco de uso del :
comando (nop):
! case ${1#[+-]} in *[!0-9]*) :;; ?*) ! :;; esac && echo Integer
Ya sea dash
, bash
, ksh
, zsh
, POSIX sh
, o posh
( "una reimplementación de la shell Bourne" sh
); El case
constructo es el más ampliamente disponible y confiable:
case $1 in (*[!0-9]*|"") false ;; (*) true ;; esac
dash
? Funciona para mí debajo bash
pero no dash
.
dash
; para interrogar el resultado que agregué echo $?
después del comando del caso.
posh
("una reimplementación del shell Bourne") tampoco tiene ningún problema con esa solución.
case
; Una de las razones es el error que usted describe, otra que en los editores que tienen características que se basan en paréntesis coincidentes (vim) brinda un soporte mucho mejor, y no menos importante personalmente me parece más legible hacer que coincidan. - WRT posh
siendo POSIX; bueno, la cita de la página de manual que di sugirió algo más, pero supongo que no se puede confiar en declaraciones tan informales de todos modos. El viejo caparazón de bourne ya no es tan significativo ahora que estamos en la era POSIX.
Puede usar la -eq
prueba en la cadena, consigo misma:
$ 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
Si el mensaje de error es un problema, redirija la salida del error a /dev/null
:
$ dash -c 'a="0xa"; [ "$a" -eq "$a" ] 2>/dev/null|| echo no'
no
" 023 "
es un número. Tenga en cuenta que funciona con guiones, pero no todos los demás shells POSIX ya que el comportamiento no se especifica si los operandos son enteros decimales de nota. Por ejemplo con ksh, diría que SHLVL
o 1+1
es un número.
Intente usarlo como una expansión aritmética y vea si funciona. En realidad, debe ser un poco más estricto que eso, porque las expansiones aritméticas ignorarían los espacios iniciales y finales, por ejemplo. Realice una expansión aritmética y asegúrese de que el resultado expandido coincida exactamente con la variable original.
check_if_number()
{
if [ "$1" = "$((${1}))" ] 2>/dev/null; then
echo "Number!"
else
echo "not a number"
fi
}
Esto también aceptaría números negativos: si realmente quiere excluirlos, agregue un cheque adicional para $((${1} >= 0))
.
[[
$(( ... ))
? Si es así, mi respuesta aún debería ser materialmente correcta, solo necesito agregar algunas citas adicionales.
check_if_number 1.2
y la función volvió: dash: 3: arithmetic expression: expecting EOF: "1.2"
Quizás con expr
?
if expr match "$1" '^\([0-9]\+\)$' > /dev/null; then
echo "integer"
else
echo "non-integer"
fi
match
tampoco \+
son POSIX. También diría que 0 no es un número. Tú quieresexpr "x$1" : 'x[0-9]\{1,\}$'
En el sistema POSIX, puede usar expr :
$ a=a
$ expr "$a" - 0 >/dev/null 2>&1
$ [ "$?" -lt 2 ] && echo Integer || echo Not Integer
expr
implementaciones dirán que 9999999999999999999 no es un número entero. POSIX no garantiza que esto funcione. En la práctica, al menos en un sistema GNU, dirá que "longitud" es un número entero.
expr 9999999999999999999 + 0
me da un estado de salida 3 expr -12 + 0
y expr length + 0
me da un estado de salida 0 con GNU expr ( + string
obliga string
a ser considerado como una cadena con GNU expr
. expr "$a" - 0
Funcionaría mejor).
-12
es un número entero válido, y 9999999999999999999
dio un desbordamiento.
Aquí hay una función simple que usa el mismo método que la respuesta de muru :
IsInteger() # usage: IsInteger string
{ # returns: flag
[ "$1" -eq "$1" ] 2> /dev/null
}
Ejemplo:
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"
Salida:
'2a3' isn't an integer
'23' is an integer
foo\n123\nbar
no es un entero, pero pasaría esta prueba.