Cercando di capire come convertire un argomento in un numero intero per eseguire l'aritmetica e quindi stamparlo, dire per addOne.sh
:
echo $1 + 1
>>sh addOne.sh 1
prints 1 + 1
Cercando di capire come convertire un argomento in un numero intero per eseguire l'aritmetica e quindi stamparlo, dire per addOne.sh
:
echo $1 + 1
>>sh addOne.sh 1
prints 1 + 1
Risposte:
In bash, non si "converte un argomento in un numero intero per eseguire l'aritmetica". In bash, le variabili sono trattate come numeri interi o stringhe a seconda del contesto.
Per eseguire l'aritmetica, è necessario richiamare l'operatore di espansione aritmetica $((...))
. Per esempio:
$ a=2
$ echo "$a + 1"
2 + 1
$ echo "$(($a + 1))"
3
o generalmente preferito:
$ echo "$((a + 1))"
3
Dovresti essere consapevole che bash (al contrario di ksh93, zsh o yash) esegue solo l' aritmetica dei numeri interi . Se hai numeri in virgola mobile (numeri con decimali), allora ci sono altri strumenti per aiutarti. Ad esempio, utilizzare 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
Oppure puoi usare una shell con supporto aritmetico in virgola mobile invece di bash:
zsh> echo $((3.14 + 1))
4.14
In bash
, puoi eseguire la conversione da qualsiasi cosa in intero usando printf -v :
printf -v int '%d\n' "$1" 2>/dev/null
Il numero fluttuante verrà convertito in intero, mentre qualsiasi cosa non assomiglierà a un numero verrà convertito in 0. L'esponenziazione verrà troncata al numero prima e
Esempio:
$ 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
printf -v
questo si può ottenere con la sostituzione del comando:int="$(printf '%d' 123.123 2>/dev/null)"
bash
te utilizzata?
Una situazione simile si è verificata di recente durante lo sviluppo di script bash da eseguire in ambienti Linux e OSX. Il risultato di un comando in OSX ha restituito una stringa contenente il codice risultato; Per esempio, " 0"
. Naturalmente, questo non è riuscito a testare correttamente nel seguente caso:
if [[ $targetCnt != 0 ]]; then...
La soluzione era quella di forzare (cioè "convertire") il risultato in un numero intero, simile a quello che ha risposto @ John1024 in modo che funzioni come previsto:
targetCnt=$(($targetCnt + 0))
if [[ $targetCnt != 0 ]]; then...
==
ecc. in [[
(anche [
noto test
) fare il confronto delle stringhe. Esistono diversi operatori per il confronto aritmetico, ad esempio [[ $targetcnt -ne 0 ]]
; vedere la pagina man (o informazioni) in Espressioni condizionali. Per tagliare gli spazi in modo specifico, è possibile utilizzare l' [
espansione variabile non quotata [ $targetcnt == 0 ]
per ottenere il wordplitting predefinito (NON eseguito in [[
), ma in generale tale approccio ti mette in pericolo.
attenzione ai codici colore, anche se in trace ( -x
) non appariranno, ciò che lo darebbe è che la stringa che dovrebbe essere un numero è racchiusa tra virgolette, non importa come lo stampi.
$((var+var))
falliscono anche sebbene se tu echo
o printf
entrambi tu sia uguale. Non conosco la correzione poiché sono stato in grado di risolverlo solo disabilitando i codici colore alla fonte dell'output. Per individuarlo nei log di traccia vedrai la variabile offensiva assegnata come var='0'
dovrebbe essere semplicementevar=0
sed
se non puoi disabilitarlo
printf "1 + %s\n" $1 won't do ?