2014-09-14 4 views
1

Je suis en train d'écrire un script où l'utilisateur entre un numéro en tant que paramètre et le script calcule la somme de tous les chiffres, par exemple,Comment puis-je obtenir un caractère d'une chaîne à un index particulier?

./myScript 963 
    18 

Donc le script prend la chaîne « 963 » et ajoute tout les caractères de la chaîne 9+6+3=18. Je pense que je pourrais obtenir la longueur de la chaîne et utiliser une boucle pour ajouter tous les index de la chaîne ensemble mais je ne peux pas comprendre comment obtenir un index de la chaîne sans connaître déjà le caractère que vous recherchez.

j'ai pu briser la chaîne à l'aide de la commande suivante,

echo "963" | fold -w1 
    9 
    6 
    3 

Mais je ne suis pas sûr si /comment je pouvais tuyau | ou rediriger > les résultats dans une variable et l'ajouter à un total à chaque fois.

Comment puis-je obtenir un caractère d'une chaîne à un index particulier?

Update:

Exemple 1:

1 = 59 $, alors le fonctionnement est 5 + 9 = 14

Exemple 2:

1 $ = 2222 puis l'opération est 2 + 2 + 2 + 2 = 8

Tous les caractères de la chaîne sont ad déduit à une somme totale.

+0

Votre but ultime n'est pas clair. Voulez-vous continuer à ajouter les chiffres ensemble jusqu'à ce qu'il vous en reste un? –

+0

Je suis avec @TomFenech dans sa confusion mais j'imagine que l'expansion de $ {parameter: offset: length} 'des variables shell sera utile ici. –

+0

Vous ajoutez tous les caractères dans la chaîne pour obtenir un total, par exemple, "55" serait "5 + 5 = 10". Quand j'obtiens la chaîne "55" je devrais retourner 10. Un autre exemple serait "22" retournerait "4". J'ai essayé de mettre à jour le poste, désolé. –

Répondre

4

Le script suivant une boucle à travers tous les chiffres dans la chaîne d'entrée et les additionne:

#!/bin/bash 

s="$1" 

for ((i=0; i<${#s}; ++i)); do 
    ((t+=${s:i:1})) 
done 

echo "sum of digits: $t" 

La syntaxe ${s:i:1} extrait une sous-chaîne de longueur 1 à partir de la position i dans la chaîne $s.

Sortie:

$ ./add.sh 963 
sum of digits: 18 

Si vous voulez continuer à ajouter ensemble les chiffres jusqu'à ce qu'il n'y avait qu'un seul reste, vous pouvez le faire à la place:

#!/bin/bash 

s="$1" 

while ((${#s} > 1)); do 
    t=0 
    for ((i=0; i<${#s}; ++i)); do 
     ((t+=${s:i:1})) 
    done 
    echo "iteration $((++n)): $t" 
    s=$t 
done 
echo "final result: $s" 

La boucle while extérieure continue aussi longtemps que la longueur de la chaîne est supérieure à 1.La boucle interne for ajoute chaque chiffre de la chaîne.

Sortie:

$ ./add.sh 963 
iteration 1: 18 
iteration 2: 9 
final result: 9 

Non pas que vous l'avez demandé, mais il y a plusieurs façons de résumer tous les chiffres dans une chaîne. Voici un autre en utilisant Perl:

$ perl -MList::Util=sum -F -anE 'say sum @F' <<<639 
18 

List::Util est un module de base en Perl. Le sous-programme sum fait une somme de réduction sur une liste pour produire une seule valeur. -a active le mode de partage automatique afin que l'entrée soit divisée dans le tableau @F. -F est utilisé pour définir le délimiteur de champ (dans ce cas, il est vide, de sorte que chaque caractère compte comme un champ séparé). -n traite chaque ligne d'entrée une par une et -E est utilisé pour entrer un doublure Perl mais avec des fonctionnalités plus récentes (telles que say) activées. say est comme print mais un retour à la ligne est ajouté à la sortie. Si vous ne connaissez pas la syntaxe <<<, elle est équivalente à echo 639 | perl ....

+0

Puis-je utiliser Perl sous Linux similaire à C? Ce qui veut dire que je peux utiliser des commandes C mélangées avec mes commandes de script bash (je pense) parce que je peux dire 'printf'. Est-ce que Perl est similaire à ça? Merci pour le code que j'aime vraiment, est-ce pour le style de la boucle C? Parce que je ne savais pas que vous pouviez les écrire comme ça ... –

+0

Des commandes comme 'printf' sont disponibles en C, Perl et tout un tas d'autres langages mais en général, vous ne pouvez pas supposer que d'autres fonctionnalités sont communes. Oui, ce style de bash loop est très similaire à celui que vous utiliseriez en C. Heureux que vous aimez le code, merci d'avoir accepté ma réponse :) –

1

Ne pas utiliser abonnement chaîne, mais le calcul de la somme souhaitée:

number=963 
sum=0 
for d in `echo "$number" | sed 's,\(.\), \1,g'` 
do 
    sum=$(($sum + $d)) 
done 
echo $sum 

Sortie: 18

0

Vous pouvez utiliser cut avec le paramètre -c pour obtenir le caractère à toute position. par exemple:

echo "963" | cut -c1 

Sorties: 9

+1

C'est assez ridiculement inefficace comparé à cela avec l'expansion des paramètres (intégrée au shell). –

1

je ferais ceci:

num="963" 
echo "$num" | grep -o . | paste -sd+ - | bc 

#or using your fold 
echo "$num" | fold -w1 | paste -sd+ - | bc 

les impressions

18 

Explication

  • le retour grep -o . chaque chiffres de votre numéro ainsi que le fold -w1
  • le paste -sd+ - fusionne les lignes à une ligne en utilisant le délimiteur + - par ex. créer une chaîne de calcul comme 9+6+3
  • le bc fait le calcul

si vous voulez scénario, par exempledigadd.sh utilisation

grep -o . <<<"$1" | paste -sd+ - | bc 

utilisant

$ bash digadd.sh    #nothing 
$ #will return nothing 

$ bash digadd.sh 1273617617273450359345873647586378242349239471289638982 
268 
$ 

Pour le plaisir, cette opération en boucle jusqu'à ce que le résultat est seulement 1 chiffre

num=12938932923849028940802934092840924 
while [[ ${#num} > 1 ]] 
do 
    echo -n "sum of digits for $num is:" 
    num=$(echo "$num" | grep -o . | paste -sd+ - | bc) 
    echo $num 
done 
echo "final result: $num" 

impressions

sum of digits for 12938932923849028940802934092840924 is:159 
sum of digits for 159 is:15 
sum of digits for 15 is:6 
final result: 6 

une autre variante amusante , quoi wi ll extraire tous les chiffres de toute chaîne est:

grep -oP '\d' <<<"$1" | paste -sd+ - | bc 

afin de l'utiliser dans le script digadd.sh comme

bash digadd.sh 9q6w3 

produit des

18 

La réponse à votre question dans le titre: Pour obtenir le Nième caractère de n'importe quelle chaîne que vous pouvez utiliser

echo "$string:POSITION:length" #position from 0 

par exemple. pour obtenir le 1er chiffre

echo "${num:0:1}" 
0

En utilisant awk:

awk 'split($0,a,""){for(i in a) sum+=i}END{print sum}' <<<$1 
0

Cela peut être fait en utilisant la manipulation substring (pris en charge par les cendres busybox, mais pas Posix sh compatible)

#!/bin/ash 
i=0 
sum=0 
while [ $i -lt ${#1} ]; do 
    sum=$((sum+${1:i:1})); 
    i=$((i+1)) 
done 
echo $sum 

Si vous vraiment doit avoir une version conforme à la coquille de posix, vous pouvez utiliser:

#!/bin/sh 
sum=0 
A=$1 

while [ ${#B} -lt ${#A} ];do 
    B=$B? 
done 

while [ "$A" ]; do 
    B=${B#?*} 
    sum=$((sum+${A%$B})) 
    A=${A#?*} 
done 

echo $sum 
Questions connexes