Manipuler un fichier via un script!

Fermé
sympaval Messages postés 19 Date d'inscription samedi 4 avril 2009 Statut Membre Dernière intervention 5 mai 2011 - 26 janv. 2011 à 23:53
zipe31 Messages postés 36402 Date d'inscription dimanche 7 novembre 2010 Statut Contributeur Dernière intervention 27 janvier 2021 - 2 févr. 2011 à 20:07
Salut à tous!

J'ai un projet pour lequel je coince un peu, et j'ai besoin de votre aide.
En fait je dois ecrire un script shell sh qui émule les fonctionnalites basiques d'une base de données, qui sera contenue dans un fichier nomé sh.db par exemple. Le script doit être écrit en sh et s'exécuter sous UNIX. Vu le délai très court pour rendre mon projet(ce weekend) et que je ne suis pas très callé en programmation shell, je viens vers vous.

Voici les fonctionnalités demandées: Pouvoir insérer une clé dans le fichier via la commande(put) ./script.sh put <key> <valeur> (si la clé existe déjà la valeur est écrasée); supprimer une entrée de la base : ./script.sh del <key> <valeur>; afficher les valeurs qui matchent avec une expression(comme avec un grep): ./script.sh select <expr>; vider la base de donnees sans supprimer le fichier: ./script.sh flush; passer le fichier en parametre avec l'option -f; creer le fichier s'il est passe en parametre et n'existe pas. Donc le script prendra des options et des parametres; et les entrees sont juste Clé=Valeur.
Pour l'insertion et la suppresion, rien ne dois être affiché à l'écran.

J'ai donc defini mon format de base de donnees sous la forme : Clé | Valeur; une entrée par ligne du fichier.
J'ai ensuite écrit mon parser d'option et les fonctions à appeler en fonction des options si la syntaxe est bonne.
Là je bloque sur la fin de mon script.
En fait pour ce script je ne dois utiliser que du sh et pas d'exécutable.
Alors voici mon problème:

Je ne peux pas ajouter les entrées en fin de fichier en faisant par exemple un echo "$key | $value" >> fichier.db, car cela ne vérifie pas l'existance de l'entrée et il y a des doublons dans les entrées de la bd; j'aimerais savoir par quelle commande interne au shell(builtin) je peux faire des check sur les lignes du fichier comme dans un tableau avant l'insertion, ceci me permettrait donc de bien gérer la commande "put" de mon sgdb(mon script).
Pour la commande "del", il faut supprimer l'entrée sans produire aucun affichage, et si le nom de la clé est juste passé en argument sans sa valeur, la clé doit restée présente mais sans contenu. J'aimerais aussi dans la mesure du possible que vous m'aidiez à ce niveau.
Pour le select il s'agit de recupérer l'expression passer en paramètres et lister toutes les valeurs de clés comportant des caractère de l'expression; de la même manière qu'un grep; seulement je n'ai pas droit au grep. Je ne sais pas si un "sed" ferais l'affaire....

J'aimerai aussi savoir quelle builtin appeler pour la création du fichier le cas échéant, et comment supprimer tout le contenu du fichier sans le supprimer lui même.

Enfin si vous avez pu répondre à mes préoccupation et que vous disposer encore d'un peu de temps, j'aimerais savoir procéder pour stocker la base de données dans le programme lui même et non plus dans un fichier externe; de quelle manière puis-je stocker les entrées et les manipuler dans ce cas? c'est une option que je devrais pouvoir gérer, mais la priorité est aux premières questions.

Merci infiniment pour votre aide précieuse.


A voir également:

4 réponses

sympaval Messages postés 19 Date d'inscription samedi 4 avril 2009 Statut Membre Dernière intervention 5 mai 2011 1
27 janv. 2011 à 12:09
Merci !

Et justement il est possible d'utiliser des commandes externes, cela a ete corrige; par contre j'ai utilise getopts pour parser mes options, ce qui est proscrit pour le projet.
Alors peux-tu me proposer une alternative?
Et pour les commande externe me permettant l'ajout, la suppression et la detection, tu aurais quelque chose a me proposer?

Merci
1
zipe31 Messages postés 36402 Date d'inscription dimanche 7 novembre 2010 Statut Contributeur Dernière intervention 27 janvier 2021 6 422
27 janv. 2011 à 12:29
Re-

par contre j'ai utilise getopts pour parser mes options, ce qui est proscrit pour le projet.
Alors peux-tu me proposer une alternative?

A part un "case ... esac" qui vérifie chaque paramètre, je ne vois pas trop ;-\


Et pour les commande externe me permettant l'ajout, la suppression et la detection, tu aurais quelque chose a me proposer?
Là par contre sans hésiter, "sed". Voir dans la FAQ toutes les pages y faisant références :
FAQ SED
et notamment :
Sed - Substitution
Sed - Supprimer une ou plusieurs lignes d'un fichier
Sed - Insertion de texte

;-))
0
zipe31 Messages postés 36402 Date d'inscription dimanche 7 novembre 2010 Statut Contributeur Dernière intervention 27 janvier 2021 6 422
27 janv. 2011 à 08:47
Salut,

En ce qui concerne l'ajout, la suppression et la détection d'entrées sans passer par des commandes externes, je ne vois pas trop ;-\

Par contre pour ce qui est de la création du fichier ou l'effacement de ses données, un simple :

> fichier

le créera s'il n'existe pas ou écrasera son contenu.
0
sympaval Messages postés 19 Date d'inscription samedi 4 avril 2009 Statut Membre Dernière intervention 5 mai 2011 1
28 janv. 2011 à 23:34
Salut , et merci pour ton aide.
J'ai pas avancer dans le projet, et la j'ai encore deux points ou je coince la.

1) Avant d'inserer une cle dans la bd, je devrais check si la cle existe afin de l'ecraser(substutition) ou alors inserer la nouvelle cle en fin de fichier. Or le format de ma bd est : "$KEY|$VALUE", et je dois verifier si la cle existe et non sa valeur, car plusieurs clefs peuvent avoir la meme valeur, mais une meme clef ne peut pas avoir plusieurs valeurs.
Pour comparer uniquement la partie a gauche du "|" au contenu de ma variable KEY, je fait un grep pour check les matches, j'ajoute un cut pour prendre le chanp qui m'interesse, et un wc pour compter les occurences ainsi je vais juste comparer le resultat a zero. mais il me semble que le wc annulle le cut. Par si le contenu de ma bd est celu i-ci:
key2|val1
key1|val1
val3|lol9
val4|lol9

Alors si je fais ./bdsh.sh put val1 abc, ca devrai en principe ajouter la clef "val1" avec la valeur "abc" en fin de fichier, car aucune clef "val1" n'existe mais ca ne marche pas, car la variable dans laquelle je recupere le resultat de mon test ne vaut pas 0; ce qui n'est pas normale car on voit bien que dans mon fichier a gauche de "|", il n'y a pas de "val1"
Voici exactement ce que je fais:
a='grep "$KEY" $db_file | cut -d "|" -f 1 | wc -l'
if [ $a != 0 ]; then
sed -i "s#\($KEY|\).*#\1$VALUE#" $db_file
else echo "$KEY|$VALUE" >> $db_file
fi
Du coup puisque a est different de 0, il doit y avoir substutition, mais la valeur de la cle n'est pas ecraser (normale car effectivement aucune clef ne correspond a "val1");

J'espere avoir un peu bien montrer la ou ca bloque. Merci de m'ouvrir les yeux la ou j'ai fait faut usage.

2) Mon deuxieme souci se situe au niveau du sed lui meme; voici le pb:

./bdsh.sh put val4 'lol\9'

En effet ceci est sense remplacer la valeur de la cle val par "lol\9" si la cle existe (ce qui est bien le cas ici), si non entrer la nouvelle cle a la fin du fichier.

mais voici l'erreur renvoyer:
sed: -e expression #1, char 22: invalid reference \9 on 's' command's RHS

Quand je met 'lol/9' a la place ou quand l'entree n'existe pas, tout se passe bien.

As-tu une idee de comment gerer ce cas specifique?

Merci une fois de plus.
0
zipe31 Messages postés 36402 Date d'inscription dimanche 7 novembre 2010 Statut Contributeur Dernière intervention 27 janvier 2021 6 422
29 janv. 2011 à 11:05
Alors pour ton 1er problème, voila une ébauche d'exemple à tester :

$ cat plop    # fichier bdd
key2|val1
key1|val1
val1|toto1
val3|lol9
val4|lol9

$ cat foo.sh     # le script
#! /bin/bash

case $1 in
select)
        
        ;;
put)
        egrep -qo "${2}\|" plop
        if [ "$?" = 0 ]
        then
                sed '/\('"${2}"'|\).*/{s//\1'"${3}"'/}' plop
        else
                echo "${2}|${3}" | tee -a plop
        fi
        ;;
del)

        ;;
flush)

        ;;
*)
        echo "Mauvais paramètre"
        exit 3
        ;;
esac

$ ./foo.sh val1 tata plop    # paramètre manquant
Mauvais paramètre

$ ./foo.sh put val1 tata plop    # substitution (ajouter "-i" à sed dans le script pour écriture)
key2|val1
key1|val1
val1|tata
val3|lol9
val4|lol9

$ ./foo.sh put val2 tata plop    # ajout entrée
val2|tata

$ cat plop    # vérification
key2|val1
key1|val1
val1|toto1
val3|lol9
val4|lol9
val2|tata

$


Pour ton 2nd problème, il faut savoir que pour "sed" cette forme "/n" (ou "n" est un entier compris entre1 et 9) correspond à une référence arrière (comme ton "\1" dans ton expression), d'où le message d'erreur vu qu'il ne trouve aucune référence numéro 9 ;-(

Il faut trouver une façon d'échapper le caractère avec les substitutions propre au shell... je cherche ça et je reviens t'en faire part ;-))
0
zipe31 Messages postés 36402 Date d'inscription dimanche 7 novembre 2010 Statut Contributeur Dernière intervention 27 janvier 2021 6 422
29 janv. 2011 à 11:33
Pour le 2nd cas, rectifie le script comme suit :

$ cat foo.sh 
#! /bin/bash                    

case $1 in
select)   

        ;;
put)      
        egrep -qo "${2}\|" plop
        if [ "$?" = 0 ]
        then
                sed '/\('"${2}"'|\).*/{s//\1'"${3/\\/\\\\}"'/}' plop
        else
                echo "${2}|${3}" | tee -a plop
        fi
        ;;
del)

        ;;
flush)

        ;;
*)
        echo "Mauvais paramètre"
        exit 3
        ;;
esac

$ ./foo.sh put val1 "lol\9" plop
key2|val1
key1|val1
val1|lol\9
val3|lol9
val4|lol9
val2|tata

$

;-))
0
sympaval Messages postés 19 Date d'inscription samedi 4 avril 2009 Statut Membre Dernière intervention 5 mai 2011 1
2 févr. 2011 à 19:44
Merci!

j'ai reussi a coder mon script comme il fallait!

merci encore.
0
zipe31 Messages postés 36402 Date d'inscription dimanche 7 novembre 2010 Statut Contributeur Dernière intervention 27 janvier 2021 6 422
2 févr. 2011 à 20:07
De rien ;-))
0