“Un argument numérique nécessaire” lorsque vous exécutez le script avec les opérations arithmétiques
Je suis en train d'écrire une fonction qui est censé convertir un horodatage de la forme h:min:sec,ms (j'.e 15:41:47,757) à quelques millisecondes. La fonction est la suivante:
#!/bin/sh
mili () {
hr=$(echo "$1" | cut -c1-2)
echo "hr is: " $hr
min=$(echo "$1" | cut -c4-5)
echo "min is: " $min
sec=$(echo "$1" | cut -c7-8)
echo "sec is: " $sec
ms=$(echo "$1" | cut -c10-12)
echo "ms is: " $ms
total=$(($hr \* 3600 + $min \* 60 + $sec) \* 1000 + $ms)
return "$total"
#echo "Result is: "$total" "
}
mili $1
Cependant, quand je le lance:
./mili.sh "15:41:47,757"
J'obtiens le message de sortie:
./mili.sh: command substitution: line 15: syntax error near unexpected token
`\*'
./mili.sh: command substitution: line 15: `($hr \* 3600 + $min \* 60 + $sec)
\* 1000 + $ms'
./mili.sh: line 17: return: : numeric argument required
J'ai essayé les variations de expr avec et sans guillemets, les guillemets doubles, et backticks mais ne peut jamais semblent au calcul de l'arithmétique. Je peux confirmer une commande simple comme cela fonctionne: expr 2 * 3 mais quand j'essaie d'utiliser quelque chose de similaire dans mon script il échoue.
Comment puis-je obtenir simplement calculer mon expression?
OriginalL'auteur Tikiyetti | 2017-08-18
Vous devez vous connecter pour publier un commentaire.
À l'intérieur de l'arithmétique, de l'
*
n'a pas besoin d'être échappé. Aussi, certaines parenthèses manquantes. Ainsi, remplacer:Avec:
Alternative
Le code peut être simplifié en évitant la nécessité pour les multiples appels à
cut
:De côté: Bash arithmétique et des signes dollar
En bash arithmétique contexte, le signe dollar avant une variable est facultative. Par exemple:
Alors que certains guides de style de recommander l'omission
$
en arithmétique contexte, il y a une différence fondamentale. Comme Chepner points dans les commentaires, le traitement des variables non définies est très différent:En somme:
Si vous voulez une variable non définie par défaut à zéro, puis omettre le
$
.Si vous voulez une variable non définie pour être remplacer par rien, ce qui pourrait causer une défaillance de l'expression, puis d'inclure le
$
.Dans la fonction shell
mili
, une variable non définiehr
,min
, etc, indique un code d'erreur et on peut vouloir un message d'erreur à nous mettre en garde à ce sujet et nous voulons comprendre la$
. Dans d'autres circonstances où une valeur par défaut de zéro est raisonnable, nous ne serions pas et l'omission de la$
serait correct.$((...))
vous pouvez utiliser des noms de variable sans$
--total=$(( ((hr * 60 + min) * 60 + sec) * 1000 + ms ))
-- je trouve l'ajout d'un des espaces à l'intérieur de la double parenthèses aider à la lisibilité.Wow...a Travaillé comme un charme. Merci man, vraiment l'apprécier. facepalm
Oui, vous avez raison, & nombre de guides de style préférez la suppression de
$
. (Je préfèrerais si bash a été conçu pour la notation de la cohérence.)Il est toujours très subtile différence entre l'utilisation de
$
et non pas: avec$
, la variable est développé avant l'expression est évaluée. La chaîne vide produit par une variable non définie va produire une défaillance de l'expression, ou au moins une expression différente de celle que vous attendiez seront évaluées. Sans le$
, la chaîne est supposé être une variable pendant de l'évaluation, avec des variables non définies par défaut les valeurs entières de 0.C'est un excellent point! J'ai juste ajouté de la discussion de la réponse.
OriginalL'auteur John1024
Un autre couple de points:
ne pas
return "$total"
: une valeur de retour est un entier entre 0 et 255. Vous devezecho "$total"
vous allez avoir des erreurs lors de l'heure/minute/seconde est
08
ou09
-- bash traite chiffres avec zéro comme octal, et 8 et 9 ne sont pas valides octale.J'écrirais:
où la
10#
de la base des forces-10 numérospuis
10#$hr
est maladroit. Une alternative${hr#0}
n'est pas mieux. bash n'est pas assez.OriginalL'auteur glenn jackman
Voici un fou alternative:
$ms3
dans la chaîne de format pour éviterecho
et une substitution de commande:date -u -d "1970-01-01 $time" +"%s$ms3"
.OriginalL'auteur glenn jackman