Simplemente no puedo entender cómo me aseguro de que un argumento pasado a mi script es un número o no.

Todo lo que quiero hacer es algo como esto:

test *isnumber* $1 && VAR=$1 || echo "need a number"

Alguna ayuda?

  • Como un aparte — el test && echo "foo" && exit 0 || echo "bar" && exit 1 enfoque está utilizando puede tener algunos efectos secundarios no deseados — si el eco se produce un error (tal vez el resultado es un cerrado FD), el exit 0 será omitido, y el código, a continuación, intente echo "bar". Si falla en eso también, la && condición fallará, y ni siquiera ejecutar exit 1! La utilización real de if declaraciones en lugar de &&/|| es menos propensos a los efectos secundarios inesperados.
  • Ese es el tipo de inteligencia que la mayoría de la gente sólo cuando ellos tienen que seguir la pista peludo errores…! Yo no creo que el echo de que podría devolver un error.
  • Poco tarde a la fiesta, pero yo sé acerca de los peligros que Charles escribió acerca de, como yo tenía que ir a través de ellos hace bastante tiempo también. Así que aquí está un 100% infalible (y bien legible) de la línea para usted: [[ $1 =~ "^[0-9]+$" ]] && { echo "number"; exit 0; } || { echo "not a number"; exit 1; } Los corchetes indican que las cosas NO deberían ser ejecutado en un subshell (que sin duda sería de esa manera con () paréntesis utiliza en su lugar). Advertencia: no te pierdas la final punto y coma. De lo contrario podría causar bash imprimir el más feo (y más inútil) mensajes de error…
  • No funciona en Ubuntu, a menos que usted no quitar las comillas. Por lo que sólo debe ser [[ 12345 =~ ^[0-9]+$ ]] && echo OKKK || echo NOOO
  • …He quitado la (incorrecta) respuesta de la pregunta; es parte de por qué las respuestas deben ser independientes, es para ser comentado, votado, corregir, etc. de forma individual.
  • Deberá ser más específica acerca de lo que entendemos por «número». Un número entero? Un número de punto fijo? Científica («e») la notación? Hay un rango requerido (por ejemplo, una de 64-bits sin signo de valor), o se le permite a cualquier número que se puede escribir?

37 Comentarios

  1. 708

    Un enfoque es el uso de una expresión regular, así:

    re='^[0-9]+$'
    if ! [[ $yournumber =~ $re ]] ; then
       echo "error: Not a number" >&2; exit 1
    fi

    Si el valor no es necesariamente un entero, considerar la modificación de la expresión regular de forma adecuada; por ejemplo:

    ^[0-9]+([.][0-9]+)?$

    …o, para el manejo de números con signo:

    ^[+-]?[0-9]+([.][0-9]+)?$
    • +1 para este enfoque, pero tenga cuidado con decimales, haciendo de esta prueba con, por ejemplo, «1.0» o «1,0» imprime «error: No es un número».
    • Me parece la «exec >&2; echo …» más bien tonto. Sólo «echo … >&2»
    • true ‘nuff. Yo tiendo a usar más complejo de los controladores de error (es decir. mucho más que sólo un «eco» de las siguientes), pero la costumbre se filtró aquí.
    • ^-*[0-9]+([.][0-9]+)?$ también prueba para los números negativos
    • ¿usted realmente desea para manejar más de un signo menos? Me gustaría hacer ^-? en lugar de ^-* a menos que usted está haciendo el trabajo para el manejo de múltiples inversiones correctamente.
    • ¿Qué exec >&2 hacer?
    • Hace que todos los futuros salida de ir a stderr. No es realmente un punto a es aquí, donde sólo hay un eco, pero es un hábito que tienden a obtener en los casos en que los mensajes de error de abarcar varias líneas.
    • Duffy también se podría considerar el caso de la flota en el formulario de .1234 sin cero a la izquierda con ^[0-9]*([.][0-9]+)?$ Esto requeriría una comprobación adicional para una cadena no vacía difícil..
    • Con la verificación completa luego de ser if ! [[ -n "$yournumber" && "$yournumber" =~ ^-?[0-9]*([.][0-9]+)?$ ]]; then echo NAN; fi
    • No estoy seguro de por qué la expresión regular tiene que ser guardado en una variable, pero si es para el bien de la compatibilidad no creo que sea necesario. Sólo se podía aplicar la expresión directamente: [[ $yournumber =~ ^[0-9]+$ ]].
    • sí, la compatibilidad. Barra diagonal inversa de manejo en literal de expresiones regulares en el lado derecho de =~ cambiado entre 3.1 y 3.2, mientras que la barra diagonal inversa en el manejo de las asignaciones es constante en todas las versiones de bash. Por lo tanto, siguiendo la práctica de asignación de expresiones regulares para las variables antes de coincidencia en contra de ellos utilizando =~ evita sorpresas. Yo lo hago aquí para enseñar buenos hábitos, aunque este particular regex no tiene barra diagonal inversa escapa.
    • Y de hecho esa es la razón por la que prefiero extendido englobamiento más de lo que ha sido de alrededor desde 2.05 b, o tal vez antes. =~ comenzó a 3.0 y ha tenido diferentes implementaciones desde entonces. Lo más difícil es que aún se necesita de caracteres de comillas en los valores de las variables que la intención de proporcionar literal (por ejemplo,${VAR//./\\.}) para evitar que se analiza como regex caracteres, mientras que con == sólo podría colocarlos en "" por ejemplo,+(x)"$V". Y la única razón por la que podría utilizar a lo largo de ext. patrones es cuando pude hacer uso de BASH_REMATCH.
    • Con respecto a la «más difícil» que parte, hay otras maneras de manejar el problema. [[ $s =~ $re_start"$literal"$re_end ]], por ejemplo, trata a la ampliación de contenidos de "$literal" como, así, literal, hay manera de escapar es necesario. (También me parece [.] considerablemente más legible y de otra manera más fácil de manejar que \., pero es cierto que bikeshedding)
    • el camino, no estoy argumentando que sólo hay una respuesta correcta. He upvoted jilles respuesta así (a pesar de que necesita el reconocido bits de extensión para completar).
    • funcionaría igual que la manera de == de partida 3.2, pero no en 3.0 o 3.1. [[ $s =~ (x) ]] sin necesidad de guardar en una variable también sólo funcionan a partir de 4.0. Extendió los patrones necesitan ser activadas una vez al inicio de la secuencia de comandos de modo que no importa realmente. También es compatible con todas las versiones de bash a partir 2.05 b, al menos. Bien estos últimos comentarios de las minas eran ya sólo acerca de por qué alguien preferiría extendido los patrones de =~. La información también podría ser útil para otros lectores, así que quizás si que cuidado con la compatibilidad.
    • No funciona para mí. «condicional operador binario espera».
    • entonces usted está tratando de utilizar con una cubierta que no es bash 3.x o más reciente. Tenga en cuenta que /bin/sh es POSIX sh (o, en los sistemas antiguos, Bourne shell), no bash, incluso cuando es un enlace simbólico a bash.
    • Tienes razón @CharlesDuffy estoy en /bin/sh. Gracias!
    • Hice if [[ 123 =~ '^[0-9]+$' ]]; then echo good; fi y no consiguió nada. Pero re='^[0-9]+$'; if [[ 123 =~ $re ]]; then echo good; fi dijo good. Por qué? ¿Tengo que escapar de algo en la primera versión?
    • poner la mano derecha de =~ en citas hace ya no es una expresión regular, pero una cadena normal (en las versiones más modernas de bash, pero no algunos de los antiguos), mientras que la versión que dio en esta respuesta se trabaja consistentemente en cada versión, donde =~ es apoyado por todos.
    • ¿Qué pasa cuando un número se inicia con un punto decimal, por ejemplo,.5? Me gustaría utilizar ^-?([0-9]*[.])?[0-9]+$ lugar.
    • ¿Por qué el «!», «=~» y «[[ ]]»? Puede alguien explicar el if/else componentes?
    • no son si los componentes — usted podría utilizar todos los constructos fuera del contexto de un if. Ver BashFAQ #31 (mywiki.wooledge.org/BashFAQ/031) para el resto; más allá de lo cubierto allí, ! invierte el estado de salida de un comando (hacer truthy cosas falsey, y falsey cosas true); es una forma común de ortografía «no» en muchos, muchos idiomas.
    • ver str="hello world"; re='[[:space:]]'; if [[ $str =~ $re ]]; then echo "matched"; fi comportarse como se espera en ideone.com/K7kM6M
    • pregunto si su entorno de ejecución implica eval o algún otro pre-etapa de ejecución. Usted puede venir para arriba con un ejemplo que no funciona sin las comillas y con un enlace al post que se ejecutan en ideone.com?
    • cavó en ella un poco más y tienes razón que funciona en ambos sentidos. no estoy seguro de lo que estaba pasando en el anterior. Gracias por sus comentarios. quita mis otros comentarios. por cierto.. no podía conseguir ideone.com para aceptar la entrada. es que una cosa?
    • La única cosa que es difícil (para mí) sobre ideone entrada implementación, es que ellos no implementar la final de salto de línea requeridos para el válido archivos de texto UNIX, pero en lugar de ir los DOS/Windows ruta de sólo poner saltos de línea entre líneas, pero no después de la última, así que read falla de la última línea introducida en el stdin cuadro (que puede ser curada por poner una línea vacía en el extremo de la stdin cuadro). Aparte de eso, sin embargo, no he tenido históricamente un problema.
    • Ser consciente de la coma decimal a partir de un punto como .3, o terminan con un punto como 3., NO va a funcionar. Me gustaría sugerir el uso de ^[+-]?([0-9]*[.])?([0-9]+)?$, sin embargo, en tres casos especiales: ., +., -. tienen que ser excluidos de la primera.

  2. 253

    Sin bashisms (funciona incluso en el Sistema V sh),

    case $string in
        ''|*[!0-9]*) echo bad ;;
        *) echo good ;;
    esac

    Rechaza las cadenas vacías y las cadenas que no contienen dígitos, la aceptación de todo lo demás.

    Negativos o números de punto flotante necesidad de un trabajo adicional. Una idea es excluir - /. en la primera «malo» patrón y agregar más «malo» de los patrones que contienen los usos inadecuados de ellos (?*-* /*.*.*)

    • +1 — este es idiomáticas, portátil camino de regreso a la original Bourne shell, y tiene soporte incorporado para glob-estilo de comodines. Si usted viene de otro lenguaje de programación, parece extraño, pero es mucho más elegante que el afrontamiento con la fragilidad de los diversos citando problemas y sin fin hacia atrás/hacia los lados problemas de compatibilidad con if test ...
    • Usted puede cambiar la primera línea para ${string#- } (que no funciona en el antiguo shells Bourne, pero funciona en cualquier POSIX) para aceptar los números enteros negativos.
    • También, esto es fácil de extender a la flota — acaba de agregar '.' | *.*.* a la desestimado patrones, y añadir punto a los caracteres permitidos. Del mismo modo, puede permitir que un signo opcional antes, aunque yo preferiría case ${string#[-+]} simplemente ignorar la señal.
    • El uso de ksh88, y esto funciona muy bien para mí!
    • Ver este para el manejo de enteros: stackoverflow.com/a/18620446/2013911
    • No debería ser case "$string" in en lugar de case $string in ?
    • Las comillas no son necesarias, ya que el comando caso de no realizar palabra la división y la ruta de acceso de la generación en la que la palabra de todos modos. (Sin embargo, las expansiones en el caso de los patrones de necesidad de citar ya que determina si la coincidencia de patrones de caracteres literal o especial.)

  3. 167

    La siguiente solución también puede ser utilizado en basic conchas como las de Bourne sin la necesidad de expresiones regulares. Básicamente, cualquier valor numérico de evaluación de operaciones que no usan números, se producirá un error que será implícitamente considerados como falsos en shell:

    "$var" -eq "$var"

    como en:

    #!/bin/bash
    
    var=a
    
    if [ -n "$var" ] && [ "$var" -eq "$var" ] 2>/dev/null; then
      echo number
    else
      echo not a number
    fi

    Usted puede también puede probar para $? el código de retorno de la operación que es más explícito:

    [ -n "$var" ] && [ "$var" -eq "$var" ] 2>/dev/null
    if [ $? -ne 0 ]; then
       echo $var is not number
    fi

    Redirección de error estándar que está ahí para ocultar la «expresión de tipo entero espera que el» mensaje » de que bash se imprime en el caso de que no disponemos de un número.

    ADVERTENCIAS (gracias a los comentarios de abajo):

    • Números con puntos decimales no identificado como válidos los «números» de
    • Utilizando [[ ]] en lugar de [ ] siempre va a evaluar a true
    • La mayoría de los no-Bash conchas siempre va a evaluar esta expresión como true
    • El comportamiento en Bash es indocumentados y por lo tanto puede cambiar sin previo aviso
    • Si el valor incluye espacios después del número (por ejemplo, «1») produce un error, como bash: [[: 1 a: syntax error in expression (error token is "a")
    • Si el valor es igual a var-name (por ejemplo, i=»i»), produce error, como bash: [[: i: expression recursion level exceeded (error token is "i")
    • Me gustaría recomendar este (pero con las variables citadas para permitir que las cadenas vacías), ya que el resultado está garantizado para ser utilizable como un número en Bash, no importa qué.
    • Tenga cuidado de usar los corchetes solo; [[ a -eq a ]] evalúa a verdadero (ambos argumentos se convierten en cero)
    • Este hecho es muy ordenado y trabaja en bash (la cual fue solicitada) y la mayoría de las conchas, pero lamentablemente no en ksh. Si quieres ser portátiles, de uso jilles » solución.
    • Muy bonito! Nota: esto sólo funciona para un número entero, y no de cualquier número. Necesitaba comprobar de un solo argumento que debe ser un número entero, por lo que esta funcionado bien: if ! [ $# -eq 1 -o "$1" -eq "$1" ] 2>/dev/null; then
    • Esto es genial. Gracias.
    • Yo les recomiendo vivamente en contra de este método debido a la no despreciable número de proyectiles cuyo [ builtin evaluará los argumentos como la aritmética. Que hay de verdadero en tanto ksh93 y mksh. Además, puesto que ambos admiten matrices, no es fácil oportunidad para la inyección de código. El uso de un patrón partido en su lugar.
    • Es cierto en bash?
    • en las versiones actuales de bash, estos se interpretan los valores numéricos de contexto de reglas sólo para [[ ]] pero no para [ ]. Dicho esto, este comportamiento está especificado por tanto el estándar POSIX para test y en bash propia documentación, en futuras versiones de bash podría modificar el comportamiento para que coincida con ksh sin romper cualquier documentadas promesas, así que depender de su actual comportamiento de la persistencia no está garantizado para estar seguro.
    • Ah ya veo, gracias por la explicación. Yo no estaba realmente preocuparse de que hace 7 años cuando escribí esto 😀
    • Estrictamente hablando, esto no es del todo «indocumentados». man test muestra -eq es para enteros y = es para las cadenas. la página man de implica, pero no dicen explícitamente -eq fallará para la comparación de cadenas.
    • ¿Cómo se puede negar esto?
    • Razón: -ne devuelve distinto de cero para los no-argumentos enteros.
    • Usted tendrá que probar que $var no es null. Yo voy a sugerir una edición: [ -n "$var" ] && [ "$var" -eq "$var" ] 2>/dev/null
    • y Alberto, ${x:-1} -eq ${x:-0} protege contra la entrada vacía.

  4. 38

    Este comprueba si un número no es entero negativo y es de shell independiente (es decir, sin bashisms) y sólo utiliza la shell construido-ins:

    INCORRECTA.

    Como esta primera respuesta (la de abajo) permite a los enteros con los personajes que en ellos mientras la primera no está primero en la variable.

    [ -z "${num##[0-9]*}" ] && echo "is a number" || echo "is not a number";

    CORRECTA .

    Como jilles comentado y sugerido en su respuesta esta es la forma correcta de hacerlo utilizando el shell-patrones.

    [ ! -z "${num##*[!0-9]*}" ] && echo "is a number" || echo "is not a number";
    • Esto no funciona correctamente, se acepta cualquier cadena que comience con un dígito. Tenga en cuenta que la PALABRA en ${VAR##PALABRA} y similares es un shell patrón, no una expresión regular.
    • Muchas gracias! Respuesta actualizada.
    • Se puede traducir esa expresión en inglés, por favor? Realmente quiero usar, pero no entiendo lo suficiente como para confiar en él, incluso después de leer la página man de bash.
    • *[!0-9]* es un patrón que coincida con todas las cadenas con al menos 1 de no-dígito. ${num##*[!0-9]*} es un «parámetro de expansión» en donde tomaremos el contenido de la num variable y quitar la cadena más larga que coincida con el patrón. Si el resultado de la expansión de parámetros no está vacío ( ! [ -z ${...} ] ), entonces es un número, ya que no contiene ningún no-dígito.
    • Por desgracia, esto no funciona si hay alguna dígitos en el argumento, incluso si no es válido el número. Por ejemplo, «exam1ple» o «a2b».
    • Ambos errores con 122s :-(

  5. 34

    Nadie sugirió bash extendida la coincidencia de patrón:

    [[ $1 == ?(-)+([0-9]) ]] && echo "$1 is an integer"
    • Glenn, me quite shopt -s extglob de su post (que me upvoted, es uno de mis favoritos respuestas aquí), ya que en Condicional Construcciones se puede leer: Cuando el == y != operadores se utilizan, la cadena a la derecha del operador es considerado un patrón y agrupados de acuerdo a las reglas que se describen a continuación en la Coincidencia de Patrón, como si el extglob shell opción habilitada. espero que no te importa!
    • En tales contextos, usted no necesita shopt extglob… eso es una buena cosa para saber!
    • de hecho, es bueno saberlo
    • Funciona bien para los simples números enteros.
    • Su solución no funciona En 3.2.25(1)-release de bash: -bash: syntax error in conditional expression: unexpected token (‘ -bash: error de sintaxis cerca `?(-‘. En esa versión, el que aparece señalado por @gniourf_gniourf no está funcionando.
    • a diferencia de extendido de coincidencia de patrón no funciona en 3.2.25 liberación como usted ha citado, el simple coincidencia de patrón funciona, por ejemplo, [[ x3x = *[[:digit:]]* ]], incluso con la sola = operador. En 3.2 man de bash páginas de la cadena de as if the extglob shell option were enabled no se encuentra.
    • tienes razón, esto se agregó en Bash 4.1 (que fue publicado a finales de 2009… Bash 3.2 fue lanzado en el 2006… ahora es un antiguo software, lo siento por aquellos que están atrapados en el pasado). También, se podría argumentar que extglobs donde introducido en la versión 2.02 (publicado en 1998), y no trabajo en <2.02 versiones… Ahora tu comentario aquí va a servir como una advertencia con respecto a las versiones anteriores.
    • La respuesta sería más fuerte si se le dio un poco más de explicación.
    • Cómo evitar los números negativos en el enfoque que usted está utilizando ? Quiero sólo números positivos.
    • quitar el ?(-) poco que opcionalmente coincide con el líder de guión, por lo que sólo la altura de dígitos con +([0-9])

  6. 26

    Me sorprende que en las soluciones directamente el análisis de los formatos de número en la concha.
    shell no es muy adecuado para este, siendo un DSL para el control de archivos y procesos.
    Hay un amplio número de analizadores un poco más abajo, por ejemplo:

    isdecimal() {
      # filter octal/hex/ord()
      num=$(printf '%s' "$1" | sed "s/^0*\([1-9]\)//; s/'/^/")
    
      test "$num" && printf '%f' "$num" >/dev/null 2>&1
    }

    Cambio ‘%f’ a lo particular formato que se requiera.

    • isnumber(){ printf '%f' "$1" &>/dev/null && echo "this is a number" || echo "not a number"; }
    • Solución agradable. printf realmente funciona muy bien, incluso los errores con algo apropiado-ish.
    • su versión se rompe la inherente (y útil) valor de retorno de la semántica de la función original. En vez de eso, simplemente salir de la función tal como es, y lo utilizan: isnumber 23 && echo "this is a number" || echo "not a number"
    • ¿No debería esto también 2>/dev/null, por lo que isnumber "foo" no contamina stderr?
    • Para llamar moderno conchas como bash «un DSL para el control de archivos y procesos» es ignorar que son utilizadas para mucho más que eso – algunas distribuciones han construido todo el paquete de los gerentes y de interfaces web (como feo como que podría ser). Los archivos por lotes ajuste a su descripción, aunque, como incluso la configuración de una variable no es difícil.
    • Es curioso que usted está tratando de ser inteligente copiando algunos de los modismos de otros idiomas. Lamentablemente esto no funciona en las conchas. Las cáscaras son muy especiales, y sin conocimiento sólido acerca de ellos, es probable que la escritura de código roto. El código está roto: isnumber "'a" devolverá true. Esto está documentado en el especificación POSIX donde se podrá leer: Si el personaje principal es un comillas simples o comillas dobles, el valor será el valor numérico en el código subyacente de que el carácter siguiente al de comillas simples o comillas dobles.
    • No es muy probable que los otros casos en que el código se va a romper. Me acabo de dar uno. Espero que el 27 de chicos que upvoted no utilizar esta crítica, el código de producción. :D.
    • Otro caso en el que falla: isinteger() { [[ $1 ]] && printf '%d' "$1" >/dev/null 2>&1; } se producirá, por ejemplo, isinteger 09: eso es debido a un tonto líder 0. Ahora se puede argumentar que 09 no debe ser validado… lo que sea, isnumber "'a" es que ya es una buena prueba de que todo este diseño está roto.
    • Nota la función fue isnumber(). Si desea más restrictivas isdecimal (), a continuación, puede filtrar con sed "s/^0*//; s/'/^/"
    • Sé que la función fue isnumber (el isinteger función que he dado es sólo un (fallido) intento de generalizar su método). Divertido, pero ahora 0 no es un número. Su función ahora genera 4 subshells, utiliza un comando externo, no funciona. Y usted afirma que un shell es sólo un DSL para el control de archivos y procesos? usted necesita para aprender mejor shell técnicas, y cuando estás más informado te vas a ver que la única manera coherente de solucionar este problema es, de hecho, analizar la cadena.
    • Por cierto, estás haciendo mal uso de printf. Por ejemplo, su función valida 42\n\n\n\n\n\n\n\n\n\n\n\n\n o %s42%s o %d9
    • Mucho mejor! sin embargo, todavía es valida variables que contienen trailing saltos de línea: $'1\n\n\n'; eso es porque $(...) adornos trailing saltos de línea. Lo que sea. Estás en el punto en el que critican los métodos que analizar la cadena de forma explícita (y por lo tanto esperamos que su método sea realmente superior), sin embargo: su método genera 3 subshells, ni siquiera es seguro al 100% (con respecto a trailling saltos de línea), de alguna manera se analiza la cadena con sed, es mucho menos eficaz que los métodos que directamente analizar la cadena. Buen trabajo.
    • Puede agregar un ejemplo de cómo llamar a esta y utilizar su resultado?
    • «Hay un amplio número de analizadores un poco más abajo» – sin embargo, usted no está utilizando uno, pero la aplicación de su propia basado en expresiones regulares solución. Desde bash tiene nativa, expresiones regulares, esta compra ¿qué es exactamente?

  7. 15

    Yo estaba buscando respuestas y…
    se dio cuenta de que a nadie se le ocurrió números en coma FLOTANTE (con punto)!

    El uso de grep es demasiado grande.

    -E significa extendido regexp

    -q significa tranquila (no echo)

    -qE es la combinación de ambos.

    A prueba directamente en la línea de comandos:

    $ echo "32" | grep -E ^\-?[0-9]?\.?[0-9]+$  
    # answer is: 32
    
    $ echo "3a2" | grep -E ^\-?[0-9]?\.?[0-9]+$  
    # answer is empty (false)
    
    $ echo ".5" | grep -E ^\-?[0-9]?\.?[0-9]+$  
    # answer .5
    
    $ echo "3.2" | grep -E ^\-?[0-9]?\.?[0-9]+$  
    # answer is 3.2

    Utilizar en un script de bash:

    check=`echo "$1" | grep -E ^\-?[0-9]*\.?[0-9]+$`
    
    if [ "$check" != '' ]; then    
      # it IS numeric
      echo "Yeap!"
    else
      # it is NOT numeric.
      echo "nooop"
    fi

    Para que coincida con SÓLO enteros, utilice esto:

    # change check line to:
    check=`echo "$1" | grep -E ^\-?[0-9]+$`
    • Las soluciones mediante el uso de awk por triple_r y tripleee trabajo con flotadores.
  8. 11

    Sólo un seguimiento a @maría. Pero porque no tengo suficiente rep, no podía publicar esto como un comentario a ese post. De todos modos, aquí es lo que he utilizado:

    isnum() { awk -v a="$1" 'BEGIN {print (a == a + 0)}'; }

    La función devuelve «1» si el argumento es un número, de lo contrario volverá a «0». Esto funciona para los números enteros, así como flotadores. El uso es algo así como:

    n=-2.05e+07
    res=`isnum "$n"`
    if [ "$res" == "1" ]; then
         echo "$n is a number"
    else
         echo "$n is not a number"
    fi
    • La impresión de un número es menos útil que la configuración de un código de salida. 'BEGIN { exit(1-(a==a+0)) }' es un poco difícil de asimilar, pero se puede utilizar en una función que devuelve true o false como [, grep -q, etc.
  9. 7
    test -z "${i//[0-9]}" && echo digits || echo no no no

    ${i//[0-9]} reemplaza cualquier dígito en el valor de $i con una cadena vacía, ver man -P 'less +/parameter\/' bash. -z comprueba si la cadena resultante tiene longitud cero.

    si usted también desea excluir el caso cuando $i está vacía, puede utilizar una de estas construcciones:

    test -n "$i" && test -z "${i//[0-9]}" && echo digits || echo not a number
    [[ -n "$i" && -z "${i//[0-9]}" ]] && echo digits || echo not a number
    • Pulgares especialmente para el man -P 'less +/parameter\/' bash parte. Aprender algo nuevo cada día. 🙂
    • no trabaja para int, < 0
    • Usted puede agregar fácilmente \- en una expresión regular para abordar el problema. Uso [0-9\-\.\+] para dar cuenta de las carrozas y los números con signo.
    • 0-0-0-0-0- ….
    • ok, por mi culpa
    • python -c $’import sys\ntrate de:\n float(sys.stdin.leer().rstrip())\nexcept:\n sys.exit(1)’ && sí echo || echo no

  10. 7

    Vieja pregunta, pero yo sólo quería añadir mi solución. Este no requiere ningún extraño shell trucos, o confiar en algo que no ha estado alrededor por siempre.

    if [ -n "$(printf '%s\n' "$var" | sed 's/[0-9]//g')" ]; then
        echo 'is not numeric'
    else
        echo 'is numeric'
    fi

    Básicamente, simplemente elimina todos los dígitos de la entrada, y si te has quedado con una cadena de longitud cero entonces no era un número.

    • Esto produce un vacío var.
    • O para las variables con espacios saltos de línea o algo así $'0\n\n\n1\n\n\n2\n\n\n3\n'.
  11. 6

    http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_04_03.html

    También puede utilizar bash clases de personaje.

    if [[ $VAR = *[[:digit:]]* ]]; then
     echo "$VAR is numeric"
    else
     echo "$VAR is not numeric"
    fi

    Numerics incluirá el espacio, el punto decimal, y «e» o «E» para punto flotante.

    Pero, si se especifica un estilo C número hexadecimal, es decir, «0xffff» o «0XFFFF», [[:digit:]] devuelve true. Un poco de trampa aquí, bash permite hacer algo como «0xAZ00» y cuenta como un dígito (¿no es esto de algún extraño capricho del compilador GCC que permiten utilizar 0x notación para las otras bases de 16???)

    Es posible que desee probar por «0x» o «0X» antes de la prueba si se trata de una numérico si su entrada es totalmente de confianza, a menos que usted desea aceptar los números hexadecimales. Que sería realizado por:

    if [[ ${VARIABLE:1:2} = "0x" ]] || [[ ${VARIABLE:1:2} = "0X" ]]; then echo "$VAR is not numeric"; fi
    • [[ $VAR = *[[:digit:]]* ]] devolverá true si la variable contiene es un número, no se si es se es un entero.
    • [[ "z3*&" = *[[:digit:]]* ]] && echo "numeric" imprime numeric. Probado en bash versión 3.2.25(1)-release.
    • la solución detecta esas cadenas que contengan, al menos, un dígito rodeado (o no) por cualquiera de los otros personajes. Yo votada abajo.
    • Obviamente el enfoque correcto es, por tanto, para revertir esto, y el uso [[ -n $VAR && $VAR != *[^[:digit:]]* ]]
    • su solución no funciona con números negativos
  12. 6

    No puede opinar todavía, así que voy a añadir mi propia respuesta, que es una extensión a glenn jackman la respuesta usando bash coincidencia de patrón.

    Original de mi necesidad era identificar los números y distinguir los números enteros y flotantes. Las definiciones de función deducirse:

    function isInteger() {
        [[ ${1} == ?(-)+([0-9]) ]]
    }
    
    function isFloat() {
        [[ ${1} == ?(-)@(+([0-9]).*([0-9])|*([0-9]).+([0-9]))?(E?(-|+)+([0-9])) ]]
    }

    He usado de la unidad de pruebas (con shUnit2) para validar mis patrones funcionado como se pretendía:

    oneTimeSetUp() {
        int_values="0 123 -0 -123"
        float_values="0.0 0. .0 -0.0 -0. -.0 \
            123.456 123. .456 -123.456 -123. -.456
            123.456E08 123.E08 .456E08 -123.456E08 -123.E08 -.456E08 \
            123.456E+08 123.E+08 .456E+08 -123.456E+08 -123.E+08 -.456E+08 \
            123.456E-08 123.E-08 .456E-08 -123.456E-08 -123.E-08 -.456E-08"
    }
    
    testIsIntegerIsFloat() {
        local value
        for value in ${int_values}
        do
            assertTrue "${value} should be tested as integer" "isInteger ${value}"
            assertFalse "${value} should not be tested as float" "isFloat ${value}"
        done
    
        for value in ${float_values}
        do
            assertTrue "${value} should be tested as float" "isFloat ${value}"
            assertFalse "${value} should not be tested as integer" "isInteger ${value}"
        done
    
    }

    Notas: El isFloat patrón puede ser modificado para ser más tolerante con punto decimal (@(.,)) y el símbolo (@(Ee)). Mi unidad de pruebas sólo los valores que son integer o float, pero no cualquier entrada no válida.

    • Lo siento, no entendía cómo la función de edición está destinada a ser utilizada.
  13. 6

    Una clara respuesta ya ha sido dada por @carlos Dufy y otros.
    Un puro bash solución sería utilizar el siguiente :

    string="-12,345"
    if [[ "$string" =~ ^-?[0-9]+[.,]?[0-9]*$ ]]
    then
        echo $string is a number
    else
        echo $string is not a number
    fi

    Aunque para los números reales no es obligatorio tener un número antes de la radix punto.

    Para proporcionar un más completo apoyo de flotación de los números y de la notación científica (muchos programas en C o Fortran o de lo contrario va a la exportación de flotación de esta manera), una adición útil a esta línea, sería la siguiente :

    string="1.2345E-67"
    if [[ "$string" =~ ^-?[0-9]*[.,]?[0-9]*[eE]?-?[0-9]+$ ]]
    then
        echo $string is a number
    else
        echo $string is not a number
    fi

    Lo que conduce a una manera de diferenciar los tipos de número, si usted está buscando algún tipo específico :

    string="-12,345"
    if [[ "$string" =~ ^-?[0-9]+$ ]]
    then
        echo $string is an integer
    elif [[ "$string" =~ ^-?[0-9]*[.,]?[0-9]*$ ]]
    then
        echo $string is a float
    elif [[ "$string" =~ ^-?[0-9]*[.,]?[0-9]*[eE]-?[0-9]+$ ]]
    then
        echo $string is a scientific number
    else
        echo $string is not a number
    fi

    Nota: se podrían enumerar los requisitos sintácticos decimales y notación científica, siendo uno de ellos para permitir la coma como radix punto, así como también «.». Entonces podríamos afirmar que no sólo debe ser uno de esos radix punto. No puede haber dos signos +/- en un [Ee] float. He aprendido un poco más las reglas de Aulu del trabajo, y la prueba en contra de los malos cadenas tales como » ‘-‘ ‘-E-1’ ‘0-0’. Aquí están mis regex/subcadena/expr herramientas que parecen estar sosteniendo:

    parse_num() {
     local r=`expr "$1" : '.*\([.,]\)' 2>/dev/null | tr -d '\n'` 
     nat='^[+-]?[0-9]+[.,]?$' \
     dot="${1%[.,]*}${r}${1##*[.,]}" \
     float='^[\+\-]?([.,0-9]+[Ee]?[-+]?|)[0-9]+$'
     [[ "$1" == $dot ]] && [[ "$1" =~ $float ]] || [[ "$1" =~ $nat ]]
    } # usage: parse_num -123.456
  14. 6
    [[ $1 =~ ^-?[0-9]+$ ]] && echo "number"

    No olvides - para incluir los números negativos!

    • ¿Cuál es el mínimo de la versión de bash? Acabo de llegar de bash: condicional operador binario espera bash: error de sintaxis cerca de testigo inesperado `=~’
    • existían al menos tan lejos como bash 3.0.
    • probablemente tuvo un problema con su primer operando, por ejemplo, demasiadas comillas o similar
    • Me preguntó acerca de la versión porque es muy es antiguo bash Solaris 7 cuadro, que todavía tenemos y que no admite =~
  15. 5

    Me gustaría probar este:

    printf "%g" "$var" &> /dev/null
    if [[ $? == 0 ]] ; then
        echo "$var is a number."
    else
        echo "$var is not a number."
    fi

    Nota: este reconoce nan e inf como número.

    • ya sea duplicado, o tal vez más apropiado como un comentario, pixelbeat la respuesta (utilizando %f es probablemente mejor de todos modos)
    • En lugar de comprobar el anterior código de estado, ¿por qué no acaba de poner en el if sí mismo? Eso es lo que if hace… if printf "%g" "$var" &> /dev/null; then ...
    • Este tiene otras advertencias. Se validará la cadena vacía, y cadenas como 'a.
  16. 4

    La forma más sencilla es para comprobar si contiene solo caracteres. Reemplazar todos los dígitos caracteres con nada y verificación de longitud. Si la longitud no es un número.

    if [[ ! -n ${input//[0-9]/} ]]; then
        echo "Input Is A Number"
    fi
    • Para manejar números negativos requeriría una más complicado enfoque.
    • … O una opcional de signo positivo.
    • me gustaría ver su enfoque si usted sabe cómo hacerlo.
  17. 4

    Como tenía que alterar este últimamente y como karttu del appoach con la unidad de prueba de la mayoría. He revisado el código y añadido algunas otras soluciones, probarlo por ti mismo para ver los resultados:

    #!/bin/bash
    
        # N={0,1,2,3,...} by syntaxerror
    function isNaturalNumber()
    {
     [[ ${1} =~ ^[0-9]+$ ]]
    }
        # Z={...,-2,-1,0,1,2,...} by karttu
    function isInteger() 
    {
     [[ ${1} == ?(-)+([0-9]) ]]
    }
        # Q={...,-½,-¼,0.0,¼,½,...} by karttu
    function isFloat() 
    {
     [[ ${1} == ?(-)@(+([0-9]).*([0-9])|*([0-9]).+([0-9]))?(E?(-|+)+([0-9])) ]]
    }
        # R={...,-1,-½,-¼,0.E+n,¼,½,1,...}
    function isNumber()
    {
     isNaturalNumber $1 || isInteger $1 || isFloat $1
    }
    
    bools=("TRUE" "FALSE")
    int_values="0 123 -0 -123"
    float_values="0.0 0. .0 -0.0 -0. -.0 \
        123.456 123. .456 -123.456 -123. -.456 \
        123.456E08 123.E08 .456E08 -123.456E08 -123.E08 -.456E08 \
        123.456E+08 123.E+08 .456E+08 -123.456E+08 -123.E+08 -.456E+08 \
        123.456E-08 123.E-08 .456E-08 -123.456E-08 -123.E-08 -.456E-08"
    false_values="blah meh mooh blah5 67mooh a123bc"
    
    for value in ${int_values} ${float_values} ${false_values}
    do
        printf "  %5s=%-30s" $(isNaturalNumber $value) ${bools[$?]} $(printf "isNaturalNumber(%s)" $value)
        printf "%5s=%-24s" $(isInteger $value) ${bools[$?]} $(printf "isInteger(%s)" $value)
        printf "%5s=%-24s" $(isFloat $value) ${bools[$?]} $(printf "isFloat(%s)" $value)
        printf "%5s=%-24s\n" $(isNumber $value) ${bools[$?]} $(printf "isNumber(%s)" $value)
    done

    Así isNumber() incluye guiones, comas y notación exponencial y, por tanto, devuelve TRUE en caso de enteros & flotadores mientras que en la otra mano isFloat() devuelve FALSE en valores enteros y isInteger() asimismo devuelve FALSE en caso de carrozas. Para su comodidad, todos como trazadores de líneas uno:

    isNaturalNumber() { [[ ${1} =~ ^[0-9]+$ ]]; }
    isInteger() { [[ ${1} == ?(-)+([0-9]) ]]; }
    isFloat() { [[ ${1} == ?(-)@(+([0-9]).*([0-9])|*([0-9]).+([0-9]))?(E?(-|+)+([0-9])) ]]; }
    isNumber() { isNaturalNumber $1 || isInteger $1 || isFloat $1; }
    • Personalmente me gustaría quitar el function de palabras clave como la de no hacer nada útil. También, no estoy seguro acerca de la utilidad de los valores de retorno. A menos que se especifique lo contrario, las funciones devolverá el estado de salida del último comando, así que usted no necesita return nada.
    • Agradable, de hecho, el returns son confusos y hacer que sea menos legible. El uso de function palabras clave o no, es más una cuestión de personal del sabor, al menos, los he borrado de los trazadores de líneas uno para ahorrar algo de espacio. thx.
    • No olvides que el punto y coma son necesarios después de las pruebas de las versiones de la línea.
    • isNumber le devuelve ‘true’ en cualquier cadena que tiene un número en él.
    • De hecho, mi false_values matriz falta ese caso. Voy a tener que mirar en él. Gracias por la sugerencia.
    • Trató de crear un combinado de expresión regex para los tres tipos. Es posible, pero esto lleva a una realidad compleja regex galimatías. Una condición de exclusión mutua se ve muy simple y legible.

  18. 4

    Yo uso expr. Devuelve un valor distinto de cero si intenta agregar un cero a un valor no numérico:

    if expr -- "$number" + 0 > /dev/null 2>&1
    then
        echo "$number is a number"
    else
        echo "$number isn't a number"
    fi

    Podría ser posible utilizar bc si usted necesita no enteros, pero no creo que bc tiene el mismo comportamiento. La adición de cero a un no-obtiene el número de cero y devuelve un valor de cero demasiado. Tal vez usted puede combinar bc y expr. Uso bc para agregar cero a $number. Si la respuesta es 0, a continuación, intente expr para comprobar que $number no es cero.

    • Esto es bastante malo. Para hacer un poco mejor debe utilizar expr -- "$number" + 0; sin embargo, esto todavía pretender que 0 isn't a number. De man expr: Exit status is 0 if EXPRESSION is neither null nor 0, 1 if EXPRESSION is null or 0,
  19. 2

    Puedo usar printf como otras respuestas se mencionó, si el suministro de la cadena de formato «%f» o «%i» printf va a hacer la comprobación para usted. Más fácil que la reinvención de los cheques, la sintaxis es simple y corto y printf es omnipresente. Así que es una opción decente en mi opinión – también se puede utilizar la siguiente idea para comprobar una serie de cosas, no sólo es útil para la comprobación de los números.

    declare  -r CHECK_FLOAT="%f"  
    declare  -r CHECK_INTEGER="%i"  
    
     ## <arg 1> Number - Number to check  
     ## <arg 2> String - Number type to check  
     ## <arg 3> String - Error message  
    function check_number() { 
      local NUMBER="" 
      local NUMBER_TYPE="" 
      local ERROR_MESG=""
      local -i PASS=1 
      local -i FAIL=0   
      case "${NUMBER_TYPE}" in 
        "${CHECK_FLOAT}") 
            if ((! $(printf "${CHECK_FLOAT}" "${NUMBER}" &>/dev/random;echo $?))); then 
               echo "${PASS}"
            else 
               echo "${ERROR_MESG}" 1>&2
               echo "${FAIL}"
            fi 
            ;;                 
        "${CHECK_INTEGER}") 
            if ((! $(printf "${CHECK_INTEGER}" "${NUMBER}" &>/dev/random;echo $?))); then 
               echo "${PASS}"
            else 
               echo "${ERROR_MESG}" 1>&2
               echo "${FAIL}"
            fi 
            ;;                 
                         *) 
            echo "Invalid number type format: ${NUMBER_TYPE} to check_number()." 1>&2
            echo "${FAIL}"
            ;;                 
       esac
    } 

    >$ var=45

    >$ (($(check_number $var "${CHECK_INTEGER}" "Error: Found $var - An integer is required."))) && { echo "$var+5" | bc; }

  20. 2

    Esto se puede lograr mediante el uso de grep para ver si la variable en cuestión coincide con una expresión regular extendida.

    Prueba entero 1120:

    yournumber=1120
    if [ $(echo "$yournumber" | grep -qE '^[0-9]+$'; echo $?) -ne "0" ]; then
        echo "Error: not a number."
    else
        echo "Valid number."
    fi

    De salida: Valid number.

    Prueba no-entero 1120a:

    yournumber=1120a
    if [ $(echo "$yournumber" | grep -qE '^[0-9]+$'; echo $?) -ne "0" ]; then
        echo "Error: not a number."
    else
        echo "Valid number."
    fi

    De salida: Error: not a number.


    Explicación

    • La grep, el -E interruptor nos permite el uso de expresiones regulares extendidas '^[0-9]+$'. Esta expresión regular significa que la variable sólo debe [] contener los números 0-9 cero a nueve de la ^ comienzo a la $ final de la variable y debe tener al menos + uno de los personajes.
    • La grep, el -q tranquilo interruptor desactiva cualquier salida o si no se encuentra nada.
    • $? es el estado de salida de la anterior comando ejecutado. Estado de salida 0 significa el éxito y nada más significa un error. El grep comando tiene un estado de salida de 0 si se encuentra una coincidencia y 1 cuando no;
    • $() es un subshell que nos permite ejecutar otro comando y, a continuación, utilizar la salida.

    Para ponerlo todo junto, en un $() subshell, nos echo la variable $yournumber y | canalizar a grep que con el -q interruptor de silencio coincide con el -E de expresiones regulares extendidas '^[0-9]+$' expresión. Luego nos echo la $? estado de salida, que sería 0 si grep encontrado con éxito un partido y 1 si no.

    Ahora, fuera de la $() subshell y de vuelta en el if condicional, tomamos la salida, ya sea 0 o 1 de la $() subshell y comprobar si es -ne no es igual a "0". Si no coinciden, el estado de salida será 1 que no coincide con "0". A continuación, vamos a echo "Error: not a number.". Si se tiene éxito a partido, el estado de salida de salida sería 0 que es igual a "0" y en ese caso más que nos echo "Valid number.".


    Para Flotadores Dobles o

    Podemos cambiar la expresión regular de '^[0-9]+$' a '^[0-9]*+\.?[0-8]+$' para flotadores o dobles.

    Prueba de flotación 1120.01:

    yournumber=1120.01
    if [ $(echo "$yournumber" | grep -qE '^[0-9]*+\.?[0-8]+$'; echo $?) -ne "0" ]; then
        echo "Error: not a number."
    else
        echo "Valid number."
    fi

    De salida: Valid number.

    Prueba de flotación 11.20.01:

    yournumber=11.20.01
    if [ $(echo "$yournumber" | grep -qE '^[0-9]*+\.?[0-8]+$'; echo $?) -ne "0" ]; then
        echo "Error: not a number."
    else
        echo "Valid number."
    fi

    De salida: Error: not a number.


    Para Los Negativos

    Para permitir a los enteros negativos, sólo cambia la expresión regular de '^[0-9]+$' a '^\-?[0-9]+$'.

    Para permitir negativo flotadores o dobles, acaba de cambiar la expresión regular de '^[0-9]*+\.?[0-8]+$' a '^\-?[0-9]*+\.?[0-8]+$'.

  21. 2

    Para mi problema, yo sólo lo necesario para asegurar que un usuario accidentalmente no escriba texto en el que por lo tanto traté de mantenerlo simple y legible

    isNumber() {
        (( $1 )) 2>/dev/null
    }

    Según el hombre de la página esta bastante mucho no lo quiero

    Si el valor de la expresión es distinto de cero, el estado de retorno es 0

    Para evitar desagradables mensajes de error para las cadenas que «podría ser números» ignoro la salida de error

    $ (( 2s ))
    bash: ((: 2s: value too great for base (error token is "2s")
  22. 1

    Para la captura de los números negativos:

    if [[ $1 == ?(-)+([0-9.]) ]]
        then
        echo number
    else
        echo not a number
    fi
    • Esto validará 1.2.3.4.5.6.7.8 o -.........
    • Además, requiere extendido de esta expansión para ser activado en primer lugar. Este es un Bash-sólo la característica de que está desactivada por defecto.
    • extendido de esta expansión se activa automáticamente cuando se utiliza == o != When the ‘==’ and ‘!=’ operators are used, the string to the right of the operator is considered a pattern and matched according to the rules described below in Pattern Matching, as if the extglob shell option were enabled. gnu.org/software/bash/manual/bashref.html#index-_005b_005b
    • Gracias por la actualización. Este parece ser un nuevo comportamiento que no es cierto en mi Bash 3.2.57 (MacOS Mojave). Veo que funciona como se describe en 4.4.
  23. 1

    Usted podría utilizar «vamos» demasiado parecido a esto :

    [ ~]$ var=1
    [ ~]$ let $var && echo "It's a number" || echo "It's not a number"
    It\'s a number
    [ ~]$ var=01
    [ ~]$ let $var && echo "It's a number" || echo "It's not a number"
    It\'s a number
    [ ~]$ var=toto
    [ ~]$ let $var && echo "It's a number" || echo "It's not a number"
    It\'s not a number
    [ ~]$ 

    Pero yo prefiero usar el «=~» Bash 3 operador+ como algunas respuestas en este hilo.

    • Esto es muy peligroso. No evaluar no validados aritmética en el shell. Debe ser validado alguna otra manera en primer lugar.
  24. 1

    Me gusta Alberto Zaccagni la respuesta.

    if [ "$var" -eq "$var" ] 2>/dev/null; then

    Requisitos importantes:
    – no subshells generado
    – no VOLVER a analizadores invoca
    – la mayoría de la cáscara de las aplicaciones no utilizan números reales

    Pero si $var es complejo (por ejemplo, un array asociativo de acceso), y si el número es un entero no negativo (la mayoría de los casos de uso), entonces este es, quizás, más eficiente?

    if [ "$var" -ge 0 ] 2> /dev/null; then ..
  25. 1
    printf '%b' "-123\nABC" | tr '[:space:]' '_' | grep -q '^-\?[[:digit:]]\+$' && echo "Integer." || echo "NOT integer."

    Quitar el -\? en grep patrón de coincidencia en caso de no aceptar entero negativo.

    • Downvote por falta de explicación. ¿Cómo funciona esto? Parece complejo y frágil, y no es obvio lo que las entradas es exactamente lo que va a aceptar. (Por ejemplo, es la eliminación de los espacios crucialmente necesario? Por qué? Se dice que un número con espacios integrados es un número válido, que puede no ser deseable.)
  26. 1

    Hizo lo mismo aquí con una expresión regular que la prueba de la parte entera y decimales parte, separados por un punto.

    re="^[0-9]*[.]{0,1}[0-9]*$"
    
    if [[ $1 =~ $re ]] 
    then
       echo "is numeric"
    else
      echo "Naahh, not numeric"
    fi
    • Podría usted explicar por qué su respuesta es fundamentalmente diferente de otras viejas respuestas, por ejemplo, Charles Duffy respuesta? Bien, la respuesta está realmente roto, ya que valida un solo período .
    • no estoy seguro de comprender el periodo solo aquí… es uno o cero periodo de espera…. Pero nada esencialmente diferente, sólo se ha encontrado la expresión regular más fácil de leer.
    • también el uso * debe coincidir con el mundo más real de los casos
    • La cosa es que eres la coincidencia de la cadena vacía a='' y la cadena de caracteres que contiene un sólo periodo de a='.' por lo que su código es un poco roto…
  27. 0

    Yo uso el siguiente (para los números enteros):

    ## ##### constants
    ##
    ## __TRUE - true (0)
    ## __FALSE - false (1)
    ##
    typeset -r __TRUE=0
    typeset -r __FALSE=1
    
    ## --------------------------------------
    ## isNumber
    ## check if a value is an integer 
    ## usage: isNumber testValue 
    ## returns: ${__TRUE} - testValue is a number else not
    ##
    function isNumber {
      typeset TESTVAR="$(echo "$1" | sed 's/[0-9]*//g' )"
      [ "${TESTVAR}"x = ""x ] && return ${__TRUE} || return ${__FALSE}
    }
    
    isNumber $1 
    if [ $? -eq ${__TRUE} ] ; then
      print "is a number"
    fi
    • Casi correcta (estás aceptando la cadena vacía), pero gratutiously complicado hasta el punto de ofuscación.
    • Incorrecto: estás aceptando -n, etc. (porque de echo), y usted está aceptando las variables con espacios saltos de línea (porque de $(...)). Y por cierto, print no es válido comando de la shell.
  28. 0

    Traté de ultrasawblade la receta de como parecía el más práctico para mí, y no podía hacer el trabajo. Al final he ideado otra forma a pesar de que, en base al igual que otros en la sustitución de parámetros, esta vez con regex de reemplazo:

    [[ "${var//*([[:digit:]])}" ]]; && echo "$var is not numeric" || echo "$var is numeric"

    Elimina todos :dígito: carácter de clase en $var y comprueba si nos quedamos con una cadena vacía, lo que significa que el original era sólo números.

    Lo que me gusta de este es su pequeño tamaño y la flexibilidad. En este formulario sólo funciona para los no delimitado, la base de 10 números enteros, a pesar de que sin duda se puede usar coincidencia de patrón para adaptarse a las necesidades de otros.

    • La lectura de mrucci la solución, que se ve casi igual que el mío, pero el uso regular de la cadena de reemplazo en lugar de «sed de estilo». Ambos utilizan las mismas reglas de coincidencia de patrones y son, AFAIK, intercambiables soluciones.
  29. 0

    Rápido & Sucio: sé que no es la forma más elegante, pero por lo general sólo agrega un cero a ella y probar el resultado. así:

    function isInteger {
      [ $(($1+0)) != 0 ] && echo "$1 is a number" || echo "$1 is not a number"
     }
    
    x=1;      isInteger $x
    x="1";    isInteger $x
    x="joe";  isInteger $x
    x=0x16 ;  isInteger $x
    x=-32674; isInteger $x   

    $(($1+0)) 0 o bomba si $1 NO es un número entero. por Ejemplo:

    function zipIt  { # quick zip - unless the 1st parameter is a number
      ERROR="not a valid number. " 
      if [ $(($1+0)) != 0 ] ; then  # isInteger($1) 
          echo " backing up files changed in the last $1 days."
          OUT="zipIt-$1-day.tgz" 
          find . -mtime -$1 -type f -print0 | xargs -0 tar cvzf $OUT 
          return 1
      fi
        showError $ERROR
    }

    NOTA: supongo que nunca pensé que para comprobar la flota o los tipos mixtos que va a hacer toda la secuencia de comandos de la bomba… en mi caso, yo no quiero ir más allá. Voy a jugar con mrucci solución y Duffy expresiones que parecen los más sólidos dentro de la bash marco…

    • Este acepta expresiones aritméticas como 1+1, pero rechaza algunos enteros positivos con los principales 0s (porque 08 no es válida constante octal).
    • Este tiene otros problemas: 0 no es un número, y está sujeta a la inyección de código, inténtelo: isInteger 'a[$(ls)]'. Ooops.
    • Y la expansión de $((...)) es no cotizadas en bolsa, una numérico IFS=123 va a cambiar.
  30. 0

    He encontrado una versión corta:

    function isnum()
    {
        return `echo "$1" | awk -F"\n" '{print ($0 != $0+0)}'`
    }
    • um.. no esta sólo devuelve 0 si la cadena no es un número? ¿Eso significa que no funciona si la cadena es "0"?
    • Toda la razón 🙂
  31. 0
    • variable para comprobar

      number=12345 o number=-23234 o number=23.167 o number=-345.234

    • de verificación numérico o no numérico

      echo $number | grep -E '^-?[0-9]*\.?[0-9]*$' > /dev/null

    • decidir sobre nuevas acciones basadas en el estado de salida de la anterior

      if [ $? -eq 0 ]; then echo "Numeric"; else echo "Non-Numeric"; fi

  32. 0

    Siguiente en David W respuesta de Oct ’13, si el uso de expr esto podría ser mejor

    test_var=`expr $am_i_numeric \* 0` >/dev/null 2>&1
    if [ "$test_var" = "" ]
    then
        ......

    Si numéricos, multiplicado por 1 da el mismo valor, (incluyendo números negativos). De lo contrario se obtiene null que usted puede probar para

    • expr es una bestia a la que es difícil de domar. No he probado esta solución, pero me gustaría evitar expr en favor de la moderna shell construido-ins a menos de compatibilidad de vuelta a legado a las conchas de la década de 1980, es un requisito importante.
  33. -1

    La aceptada respuesta no trabajo para mí en todos los casos BASH 4+ así :

    # -- is var an integer? --
    # trim leading/trailing whitespace, then check for digits return 0 or 1
    # Globals: None
    # Arguments: string
    # Returns: boolean
    # --
    is_int() {
        str="$(echo -e "${1}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
        case ${str} in ''|*[!0-9]*) return 1 ;; esac
        return 0
    }

    ¿Cómo se usa ?

    Válido (0 = true):

    is_int "100" && echo "return 0" || echo "return 1"

    No válido (devolverá 1 = false) :

    is_int "100abc" && echo "returned 0" || echo "returned 1"
    is_int ""  && echo "returned 0" || echo "returned 1"
    is_int "100 100"  && echo "returned 0" || echo "returned 1"
    is_int "      "  && echo "returned 0" || echo "returned 1"
    is_int $NOT_SET_VAR  && echo "returned 0" || echo "returned 1"
    is_int "3.14"   && echo "returned 0" || echo "returned 1"

    De salida:

    returned 0
    returned 1
    returned 1
    returned 1
    returned 1
    returned 1
    returned 1

    nota, en Bash, 1 = false, 0 = true. Yo soy simplemente imprimirlo donde en lugar de algo como esto sería más probable :

    if is_int ${total} ; then
        # perform some action 
    fi
    • Podría preguntarle a mostrar un caso concreto, la aceptaron no tiene la respuesta a trabajar?
    • …por cierto, echo -e va a implantar la portabilidad de errores — en algunas de las conchas se imprime -e en la salida (y las conchas donde no de hacerlo está violando la carta de la especificación POSIX para echo; con el conjunto adecuado de tiempo de ejecución de los indicadores establecidos para hacerla más estrictamente compatible que de costumbre, esto significa bash también puede imprimir -e en la salida cuando se ejecuta echo -e).
  34. -3

    La aceptada respuesta no trabajo aquí, estoy en MacOS. El siguiente código funciona:

    if [ $(echo "$number" | grep -c '^[0-9]\+$') = 0 ]; then 
        echo "it is a number"
    else
        echo "not a number"
    fi
    • Esto tiene muchos problemas: el más evidente es la que se debe comparar con 1 y no 0 en la prueba de declaración. El otro problema es que si la variable number contiene saltos de línea: number=$'42\nthis is not a number, right?' será validado.
    • Eh? El aceptó contestar, efectivamente, el trabajo en MacOS. Por favor, que lo comente con los detalles de la edición visto, y (idealmente) un reproductor. (Sospecho que tal vez estaba siendo administrado bajo /bin/sh, ya sea a través de un #!/bin/sh shebang o con una secuencia de comandos comenzó con sh scriptname — en lugar de bash).
    • El uso de grep -c en una sustitución de comandos y comparar el resultado a 0 es un común y extremadamente complicado antipattern. Consulte inútil el uso de grep y el «pretzel logic» subpágina.
  35. -3

    Pila apareció un mensaje que me preguntó si realmente quiero respuesta después de 30+ respuestas? Pero, por supuesto!!!
    Usar bash nuevas características y aquí está: (después de que el comentario que me hizo un cambio)

    función isInt() { ([[ $1 -eq $(( $1 + 0 )) ]] 2>/dev/null &&
    [[ $1 != «]] && echo 1) || echo » }

    function isInt() {
       ([[ $1 =~ ^[-+0-9]+$  ]] && [[ $1 -eq $(( $1 + 0 )) ]] 2>/dev/null && [[ $1 != '' ]] && echo 1) || echo ''
    }

    Admite:

    ===============out-of-the-box==================
     1. negative integers (true & arithmetic),
     2. positive integers (true & arithmetic),
     3. with quotation (true & arithmetic),
     4. without quotation (true & arithmetic),
     5. all of the above with mixed signs(!!!) (true & arithmetic),
     6. empty string (false & arithmetic),
     7. no value (false & arithmetic),
     8. alphanumeric (false & no arithmetic),
     9. mixed only signs (false & no arithmetic),
    ================problematic====================
     10. positive/negative floats with 1 decimal (true & NO arithmetic),
     11. positive/negative floats with 2 or more decimals (FALSE & NO arithmetic).

    Verdadero/falso, es lo que se obtiene a partir de la función sólo cuando se utiliza combinado con el proceso de sustitución como en [[ $( isInt <arg> ) ]] ya que no hay lógico tipo en bash ni volver valor de la función.

    Yo uso el capital cuando el resultado de la prueba de expresión está MAL considerando, que debería ser al revés!

    Por ‘aritmética’ me refiero a bash puede hacer matemáticas como en esta expresión: $x=$(( $y + 34)).

    Yo uso ‘aritmética/no hay aritmética’ cuando en expresiones matemáticas el argumento actúa como se espera y ‘NO hay aritmética» cuando se porta mal en comparación con lo que se espera.

    Como se puede ver, no sólo de 10 y 11 son las problemáticas queridos!

    Perfecto!

    PS: tenga en cuenta que el la MAYORÍA de los respuesta popular falla en caso de que 9!

    • No, por favor no!!! esto es completamente roto! y es sujeto a la ejecución de código arbitrario. Pruébelo usted mismo: isInt 'a[$(ls>&3)]' 3>&1. Estás contenta de que yo sólo se utiliza ls como un comando (que se ejecuta dos veces). Y el código también afirma que a[$(ls>&3)] es un número.
    • Por no mencionar que afirman que cualquier nombre de variable válido (que no está definida o se expande a un número o vacío, o de forma recursiva se expande a un número o vacío) es un número. E. g., unset a; isInt a.
    • la ejecución de código arbitrario por medio de quién? usted toma la responsabilidad de escribir sudo su, pero no para ejecutar este o cualquier secuencia de comandos?
    • si [[ isInt ‘a[$(ls>&3)]’ ]]; then … es seguro, ya que da errores…! Te refieres a la ejecución directa isInt ‘a[$(ls>&3)]’ …. entonces no lo llames directo!! Que implican lo que si el rm estaba dentro … yo le contestaría que no, no saben lo que rm no?’ Estoy de acuerdo, acabo de probarlo y ACEPTAR su bajo condiciones! Como es la vida!
  36. -4

    Esto es un poco áspero alrededor de los bordes, pero un poco más novatos amable.

    if [ $number -ge 0 ]
    then
    echo "Continue with code block"
    else
    echo "We matched 0 or $number is not a number"
    fi

    Esto provocará un error de impresión y «Ilegal número:» si $número no es un número, pero no va a salir de la secuencia de comandos. Curiosamente no hay una opción de prueba de que yo pudiera encontrar a prueba por un número entero.
    La lógica aquí coincide con cualquier número que sea mayor que o igual a 0.

    • Su prueba de la falta a 0, por no hablar de los números negativos.
    • además, requiere [[ ]], en lugar de [ ], de lo contrario se produce un error en no enteros, cadenas de caracteres.
    • Una cadena como a también pasa esta prueba. Quiero downvote…
    • [ «$numero» -ge 0 2>/dev/null ] && echo isNumber || echo noNumber
  37. -5

    A continuación es un Guión escrito por mí y se utilizan para una secuencia de comandos de integración con Nagios y está funcionando correctamente hasta ahora

    #!/bin/bash
    # Script to test variable is numeric or not
    # Shirish Shukla
    # Pass arg1 as number
    a1=$1
    a=$(echo $a1|awk '{if($1 > 0) print $1; else print $1"*-1"}')
    b=$(echo "scale=2;$a/$a + 1" | bc -l 2>/dev/null)
    if [[ $b > 1 ]]
    then
        echo "$1 is Numeric"
    else
        echo "$1 is Non Numeric"
    fi

    Por ejemplo:

    # sh isnumsks.sh   "-22.22"
    -22.22 is Numeric
    
    # sh isnumsks.sh   "22.22"
    22.22 is Numeric
    
    # sh isnumsks.sh   "shirish22.22"
    shirish22.22 is Non  Numeric
    • Esto es complejo y roto. Usted necesita el doble de citas en echo "$a1", de lo contrario los comodines de la cadena se expandió y el resultado depende de lo que los archivos están en el directorio actual (prueba isnumsks.sh "*", a continuación, inténtelo de nuevo después de crear un archivo llamado 42). Sólo estás buscando en el primer espacio en blanco delimitado por la palabra, por lo que 42 psych está mal clasificado como numérico. Todos los tipos de entrada que no sean numéricos, pero válida bc sintaxis de tornillo de esto, por ejemplo,2012-01-03.

Dejar respuesta

Please enter your comment!
Please enter your name here