Le premier script Bash contrôle les coûts

Sep 15 2020

Il y a quelques jours, j'ai écrit mon premier script Bash - j'ai fait une très petite chose il y a quelques années - pour garder mes coûts sous contrôle et en avoir un aperçu. Par conséquent, je veux qu'il inclue l'ajout, l'affichage et la modification des coûts. Cela fonctionne comme je l'ai écrit, mais je ne suis pas vraiment sûr que ce soit la "meilleure" façon de le faire. Je voulais aussi avoir un aperçu de l'argent dépensé pour le mois en cours, mais je ne sais pas comment le faire.

Si vous avez quelques minutes pour jeter un œil au code, je l'apprécierais beaucoup.

#!/bin/bash

##declaration of Variables

#path to saving files
SavingFile=/home/tobias/TestSkripte/SpeicherBuchhaltung

Budget=$(cut -d= -f2 $SavingFile)
CostsHousehold=$(cut -d= -f4 $SavingFile)
CostsCar=$(cut -d= -f6 $SavingFile)
CostsLuxury=$(cut -d= -f8 $SavingFile)
CostsStudy=$(cut -d= -f10 $SavingFile)
CostsFood=$(cut -d= -f12 $SavingFile)
CostsHygiene=$(cut -d= -f14 $SavingFile)
CostsEntertainment=$(cut -d= -f16 $SavingFile)
CostsOther=$(cut -d= -f18 $SavingFile)
CostsMonthly=$(cut -d= -f20 $SavingFile)
CostsAll=$(cut -d= -f22 $SavingFile)
CostsMonthlyOld=

# check if script is called with parameters - if not show current budget
if [ $# -gt 0 ] then case $1 in
                # add amount to *Costs and subtract it from the given budget
                "-a")
                        case $2 in #asigning variables for chosen *Costs #for adding *Costs only change or append lines in case statement "-h") CostsTemp=$CostsHousehold; CostsName=CostsHousehold;;
                                "-c") CostsTemp=$CostsCar; CostsName=CostsCar;; "-l") CostsTemp=$CostsLuxury; CostsName=CostsLuxury;;
                                "-s") CostsTemp=$CostsStudy; CostsName=CostsStudy;; "-f") CostsTemp=$CostsFood; CostsName=CostsFood;;
                                "-y") CostsTemp=$CostsHygiene; CostsName=CostsHygiene;; "-e") CostsTemp=$CostsEntertainment; CostsName=CostsEntertainment;;
                                "-o") CostsTemp=$CostsOther; CostsName=CostsOther;; esac; #add given amount to chosen *Costs CostsNew=$((CostsTemp+$3)); #save new Costs sed -i "s/$CostsName=$CostsTemp/$CostsName=$CostsNew/g" "$SavingFile";
                        #save new calculated Budget to file
                        BudgetNew=$((Budget-$3));
                        sed -i "s/Budget=$Budget/Budget=$BudgetNew/g" "$SavingFile";; #change the value of Budget or *Costs "--change") #check if there are three options given --> if not you cant add costs if [ $# -eq 3 ] ; then

                                #check input what shall be changed, if wanted only change/add options here
                                case $2 in "-b") nameTemp=Budget; changeTemp=$Budget;;
                                        "-h") nameTemp=CostsHousehold; changeTemp=$CostsHousehold;; "-c") nameTemp=CostsCar; changeTemp=$CostsCar;;
                                        "-l") nameTemp=CostsLuxury; changeTemp=$CostsLuxury;; "-s") nameTemp=CostsStudy; changeTemp=$CostsStudy;;
                                        "-f") nameTemp=CostsFood; changeTemp=$CostsFood;; "-y") nameTemp=CostsHygiene; changeTemp=$CostsHygiene;;
                                        "-e") nameTemp=CostsEntertainment; changeTemp=$CostsEntertainment;; "-o") nameTemp=CostsOther; changeTemp=$CostsOther;;
                                esac;

                                #changing the values in the saving File
                                sed -i "s/$nameTemp=$changeTemp/$nameTemp=$3/g" "$SavingFile" #print error if there are not three options given else printf "%-s \n" "no value given, please run again with value" fi;; #print wanted costs "--print") #assigning variables for case statement so they can be printed wiht -t otherwise they could be printed in case statement directly without variables printB="Amount of Budget: $Budget"
                        printH="Household costs: $CostsHousehold" printC="Car costs: $CostsCar"
                        printL="Luxury costs: $CostsLuxury" printS="Sutdy costs: $CostsStudy"
                        printF="Food costs: $CostsFood" printY="Hygine costs: $CostsHygiene"
                        printE="Enternainment costs: $CostsEntertainment" printO="Other costs: $CostsOther"
                        printA="All costs added together are: $((CostsHousehold + CostsCar + CostsLuxury + CostsStudy + CostsFood + CostsHygiene + CostsEntertainment + CostsOther))" case $2 in
                                "-b") printf "%s \n" "$printB";; "-h") printf "%s \n" "$printH";;
                                "-c") printf "%s \n" "$printC";; "-l") printf "%s \n" "$printL";;
                                "-s") printf "%s \n" "$printS";; "-f") printf "%s \n" "$printF";;
                                "-y") printf "%s \n" "$printY";; "-e") printf "%s \n" "$printE";;
                                "-o") printf "%s \n" "$printO";; "-a") printf "%s \n" "$printA";;
                                "-t") printf "%s \t \t" "$printH"; printf "%-s \n" "$printC";
                                      printf "%s \t \t" "$printL"; printf "%-s \n" "$printS";
                                      printf "%s \t \t" "$printF"; printf "%-s \n" "$printY";
                                      printf "%s \t " "$printE"; printf "%-s \n" "$printO";
                                      printf "%s \n" "$printA"; printf "%s \n" "$printB";;

                        esac;;



                #shows help; if new *Cost is changed/added, change help option too so it stays up to date
                "--help")
                        #adding costs
                        printf "%-s \n \t" "-a: add following costs:";
                        printf "%-s \n \t" "-h: Household related costs";
                        printf "%-s \n \t" "-c: car related costs";
                        printf "%-s \n \t" "-l: luxury related costs";
                        printf "%-s \n \t" "-s: stutdy related costs";
                        printf "%-s \n \t" "-f: food related costs";
                        printf "%-s \n \t" "-y: hygiene article related costs";
                        printf "%-s \n \t" "-e: entertainment related costs";
                        printf "%-s \n \n" "-o: other related costs";
                        #change costs
                        printf "%-s \n \t" "--change: change the value of the following costs:";
                        printf "%-s \n \t" "-b:  budget";
                        printf "%-s \n \t" "-h: household";
                        printf "%-s \n \t" "-c: car";
                        printf "%-s \n \t" "-l: luxury";
                        printf "%-s \n \t" "-s: study";
                        printf "%-s \n \t" "-y: hygiene";
                        printf "%-s \n \t" "-e: entertainment";
                        printf "%-s \n \n"   "-o: other";
                        #show costs
                        printf "%-s \n \t" "--print: prints following costs:";
                        printf "%-s \n \t" "-b:  budget";
                        printf "%-s \n \t" "-h: household";
                        printf "%-s \n \t" "-c: car";
                        printf "%-s \n \t" "-l: luxury";
                        printf "%-s \n \t" "-s: study";
                        printf "%-s \n \t" "-y: hygiene";
                        printf "%-s \n \t" "-e: entertainment";
                        printf "%-s \n \t" "-o: other";
                        printf "%-s \n \t" "-a: all costs added together";
                        printf "%-s \n \t" "-t: print all costs and budget";;



        esac

else
       printf "%-s \n" $Budget
fi

Restez en bonne santé et passez un bon moment.

Réponses

2 chicks Sep 16 2020 at 09:57

Bienvenue dans Code Review. J'ai aimé lire votre script. Merci de l'avoir soumis à l'examen du code.

Bonnes choses

  • Vos noms de variables sont bons.
  • Les commentaires sont très bons.
  • L'indentation à 8 espaces réchauffe le cœur de quelqu'un qui est bloqué avec du code python à 4 espaces depuis trop longtemps. J'aime la façon dont vos déclarations de cas internes ont le tout sur une seule ligne, mais si c'était pour du code qui allait être maintenu par d'autres personnes, il serait préférable de l'étaler sur plus de lignes.
  • Vous avez bien cité la plupart des choses, mais shellcheck vous dirait de ne pas avoir cité toutes les substitutions de variables, au cas où il y aurait de l'espace dedans et causerait des problèmes. Dans la plupart des cas, vous le réglez pas loin au-dessus, il y a donc peu de chances que de l'espace s'infiltre, mais c'est une bonne habitude à prendre.

Suggestions

  • Déplacez chaque option dans un fichier function.
  • Utilisez la [[forme de conditionnels pour éviter certains cas de bord désagréables.
  • Ajoutez au moins un espace après le #délimiteur de commentaire.
  • Essayez shellcheck .
  • Pensez à changer votre ligne sh-bang #!/usr/bin/env bashpour rendre votre script portable dans des environnements qui se trouvent bashdans des endroits étranges.

Le magasin de données

Il m'a fallu une minute de lecture pour comprendre comment fonctionnait le magasin de données et j'ai été très impressionné par l'ensemble. C'est une configuration assez inhabituelle, mais avant de parler de moyens plus traditionnels de le faire, voyons comment la conception existante pourrait être améliorée.

  • La première chose à propos d'un format de données personnalisé est de le documenter. J'ajouterais ceci comme une série de commentaires en haut du fichier. Inclure un exemple de ce à quoi il est censé ressembler ferait des merveilles pour quelqu'un qui n'a jamais vu cela auparavant.
  • Je suis assez content de la façon dont l'écriture dans le fichier fonctionne. seddevrait faire ça bien la plupart du temps et j'espère que vous avez des sauvegardes. Un défaut potentiel de votre implémentation est que vous pourriez avoir deux clés dont le nom est ambigu. Si vous aviez Foo=1et BarFoo=2, la mise à jour Foo=3changerait les deux. Ceci est facile à corriger en ajoutant un ^au début de la partie match de l'expression régulière.
  • La lecture du fichier est un peu plus problématique. Votre code dépend de la position des champs dans le fichier, mais le code serait plus facile à lire et résilient aux nouveaux champs ajoutés au milieu si vous utilisez le même schéma de variables que vous utilisez pour écrire dans le fichier.
  • Le fichier ne serait-il pas plus lisible par l'homme si les paires clé-valeur étaient une par ligne au lieu d'une longue ligne?

Tout cela conduit vraiment à la question: pourquoi ne pas utiliser une base de données? Créer une table dans une base de données SQL et mettre chaque coût dans un enregistrement faciliterait également le total. Vous pouvez accéder à PostgreSQL ou SQLite à partir de la ligne de commande. Les deux seraient plus résilients et évolutifs que d'écrire vos propres trucs pour jouer avec un fichier texte.

Votre magasin de données actuel est essentiellement un magasin clé-valeur. Il y en a beaucoup ces jours-ci. La dbmfamille est sous UNIX depuis des décennies. Les alternatives de l'ère Internet incluent riak, cassandra, scylladb et bien d'autres. Celles-ci s'adapteront plus facilement à votre modèle de données actuel que le passage à SQL, mais SQL vous donnera des capacités de "reporting" gratuitement où vous devrez le construire vous-même avec les magasins de valeurs clés.