Argumento de cadena a entero en bash

74

Intentando descubrir cómo convertir un argumento en un entero para realizar operaciones aritméticas y luego imprimirlo, digamos para addOne.sh:

echo $1 + 1
>>sh addOne.sh 1
prints 1 + 1
usuario135986
fuente
Intento formatear su pregunta, pero de alguna manera sigue sin estar clara. printf "1 + %s\n" $1 won't do ?
Archemar

Respuestas:

89

En bash, uno no "convierte un argumento en un entero para realizar operaciones aritméticas". En bash, las variables se tratan como un entero o una cadena según el contexto.

Para realizar la aritmética, debe invocar el operador de expansión aritmética $((...)). Por ejemplo:

$ a=2
$ echo "$a + 1"
2 + 1
$ echo "$(($a + 1))"
3

o generalmente preferido:

$ echo "$((a + 1))"
3

Debe tener en cuenta que bash (a diferencia de ksh93, zsh o yash) solo realiza aritmética de enteros . Si tiene números de coma flotante (números con decimales), existen otras herramientas para ayudarlo. Por ejemplo, use bc:

$ b=3.14
$ echo "$(($b + 1))"
bash: 3.14 + 1: syntax error: invalid arithmetic operator (error token is ".14 + 1")
$ echo "$b + 1" | bc -l
4.14

O puede usar un shell con soporte aritmético de coma flotante en lugar de bash:

zsh> echo $((3.14 + 1))
4.14
John1024
fuente
Usar $ (()) o (()) no es seguro si no sabe cuáles son las cadenas (como la entrada del usuario). Considere esto: foo = foo ((foo + = 0)) Esto bloqueará el script mientras intenta evaluar recursivamente foo. Lo mismo con: foo = foo foo = $ ((foo + 0))
art
12

De otra manera, puedes usar expr

Ex:

$ version="0002"
$ expr $version + 0
2
$ expr $version + 1
3
Nam
fuente
10

En bash, puede realizar la conversión de cualquier cosa a entero usando printf -v :

printf -v int '%d\n' "$1" 2>/dev/null

El número flotante se convertirá en entero, mientras que cualquier cosa que no parezca un número se convertirá en 0. La exponenciación se truncará en el número anterior e

Ejemplo:

$ printf -v int '%d\n' 123.123 2>/dev/null
$ printf '%d\n' "$int"
123
$ printf -v int '%d\n' abc 2>/dev/null
$ printf '%d\n' "$int"
0
$ printf -v int '%d\n' 1e10 2>/dev/null
$ printf '%d\n' "$int"
1
Cuonglm
fuente
2
En otros proyectiles sin printf -vesto se puede lograr con la sustitución de comandos:int="$(printf '%d' 123.123 2>/dev/null)"
Adrian Günter
2
Esto no funciona en bash.
Michael Martinez
@MichaelMartinez ¿estás seguro? ¿Qué versión de bashusted usó?
Cuonglm
GNU bash, versión 4.2.46 (1) -release (x86_64-redhat-linux-gnu)
Michael Martinez
5

Una situación similar surgió recientemente al desarrollar scripts de bash para ejecutarse en entornos Linux y OSX. El resultado de un comando en OSX devolvió una cadena que contiene el código de resultado; es decir, " 0". Por supuesto, esto no se pudo probar correctamente en el siguiente caso:

if [[ $targetCnt != 0 ]]; then...

La solución fue forzar (es decir, 'convertir') el resultado a un número entero, similar a lo que @ John1024 respondió anteriormente para que funcione como se esperaba:

targetCnt=$(($targetCnt + 0))
if [[ $targetCnt != 0 ]]; then...
JESii
fuente
3
==etc en [[(también [conocido como test) hacer una comparación de cadenas. Existen diferentes operadores para la comparación aritmética, por ejemplo [[ $targetcnt -ne 0 ]]; vea la página de manual (o información) en Expresiones condicionales. Para recortar espacios específicamente, puede usar [una expansión variable sin comillas [ $targetcnt == 0 ]para obtener una división de palabras predeterminada (NO se hace en [[), pero en general ese enfoque lo lleva al peligro.
dave_thompson_085
-2

importa los códigos de color, incluso en trace ( -x) no aparecerán, lo que lo delataría es que la cadena que se supone que es un número está entre comillas, sin importar cómo la imprima.

deshacer
fuente
1
Votado abajo, ya que encuentro su respuesta un poco confusa. ¿Quizás podría agregar a lo que se debe corregir el script?
Time4Tea 01 de
esta fue la respuesta principal en la búsqueda de bash + integer + string, así que agregué una información relacionada que no se incluyó entre las respuestas, es decir, cuando las cadenas están envueltas en códigos de colores, puede que no esté claro por qué operaciones como $((var+var))fallar incluso aunque si tú echoo printfambos vares son lo mismo. No conozco la solución, ya que solo pude solucionarla deshabilitando los códigos de color en la fuente de la salida. Para detectarlo en los registros de seguimiento, verá la variable asignada como infractor var='0'mientras que debería ser simplementevar=0
untore
Lo que puede hacer es asegurarse de que la salida no tenga códigos de color sedsi no puede deshabilitarla
Desinstale