¿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 dashy 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 caseconstructo es el más ampliamente disponible y confiable:
case $1 in (*[!0-9]*|"") false ;; (*) true ;; esac
dash? Funciona para mí debajo bashpero 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 poshsiendo 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 -eqprueba 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 SHLVLo 1+1es 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.2y 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
matchtampoco \+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
exprimplementaciones 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 + 0me da un estado de salida 3 expr -12 + 0y expr length + 0me da un estado de salida 0 con GNU expr ( + stringobliga stringa ser considerado como una cadena con GNU expr. expr "$a" - 0Funcionaría mejor).
-12es un número entero válido, y 9999999999999999999dio 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\nbarno es un entero, pero pasaría esta prueba.