Mais ça ne marche pas. La commande m'affiche (et remplace) dans l'ensemble du document et pas uniquement la ligne concernée.
J'ai vérifié, la variable $nlign contient bien un simple numéro. J'ai essayé plusieurs syntaxes mais rien n'y fait. J'ai soit une erreur, soit ça ne fait pas ce que je demande.
Une idée ?
J'en profite pour anticiper sur une potentielle question à venir, mais comment faire pour que sed me modifie directement le fichier, et ne m'affiche rien à l'écran ?
Merci pour ce retour ; cependant, je ne vois pas où intervient la variable contenant le numéro de ligne dans ton exemple... A savoir, je n'ai mis qu'une partie de mon script pour exposer le problème, mais en réalité, dans mon projet, une même ligne est modifiée plusieurs fois de suite, d'où l’intérêt de conserver le numéro de cette dernière.
Je ne l'ai pas mis, mais la ligne passe de "todo" à "runing" puis à "done". Ainsi, la ligne correspondant à la première occurrence de "todo", une fois modifiée, n'est pas forcément la même que la première occurrence de "running".
Il m'est donc nécessaire, à moins que je modifie un peu le processus que j'avais en tête, de pouvoir donner le numéro de ligne en variable. C'est la seule chose qui me permet d'identifier facilement quoi modifier dans mon fichier.
Je n'ai pas les éléments sous les yeux dans l’immédiat, mais si besoin, je pourrais peut-être poster le script complet ce soir pour que ce soit plus clair.
donne également un échantillon représentatif du fichier à traiter, et les modifications attendues, ainsi que les éventuels messages d'erreurs complets.
Validez la réponse utile « Un problème clairement exposé est à moitié résolu. » Pas de MP technique
Le fichier est présent dans un dossier partager sur le réseau, accessible par plusieurs machines (entre 1 et 4). Toutes les tâches doivent être réalisées une seule fois, peu importe la machine qui la réalise, et peu importe l'ordre. Ainsi, lorsqu'une machine commence une tâche, elle change le flag "todo" en "computing" et une fois la tâche finie, elle passe le flag en "done". Alors, elle cherche l'opération suivante comportant le flag "todo" et recommence tant qu'il existe des flags "todo". Chaque machine sur le réseau agit de la sorte.
Ainsi, en cours de fonctionnement, il peut y avoir plusieurs lignes portant le flag "todo", "computing" et "done".
Actuellement, voici le script que chaque machine devra exécuter :
#!/bin/bash
#script à run en SUDO...
#Ce script permet de lancer récursivement les tâches présentes dans la TaskList (le $1)
todo=$(grep -m1 -i "todo: " $1 | sed 's/todo: //g')
while [ "$todo" != "" ]
do
nlign=$(grep -nm1 -i todo: $1 | cut -d ':' -f1)
sed "${nlign}s/todo: /computing: /g" $1
exec $todo
sed "${nlign}s/computing: /done: /g" $1
todo=$(grep -m1 -i "todo: " $1 | sed 's/todo: //g')
done
echo "No more tasks to do..."
exit 0
Mais j'ai des bugs avec le sed.... J'ai bien entendu fait l'essai sur une seule ligne en particulier (sans boucle et avec numéro de ligne fixe), ça marche sans soucis.
L'erreur que j'ai est simplement que je passe en boucle infinie car pas de modification des flags (je ne fais qu'afficher l'ensemble du fichier texte).
Voilà, ce n'est très certainement pas la meilleure méthode (pas la plus performante en tout cas) pour faire du calcul partagé, mais si je peux éviter de me faire le truc en C, qui serait trop spécifique, c'est cool.
while true
do
nbL=$(awk '/^todo:/{print NR; exit}' taskList)
((nbL)) || break
sed -i $nbL's/todo/running/' taskList
echo "traitement ligne #$nbL en cours"
if commande_de_traitement
then
sed -i $nbL's/running/done/' taskList
else
sed -i $nbL's/running/failed/' taskList
fi
done
mais je ne garantis pas qu'il n'y aura pas de "chevauchements" dûs entre autre à la disponibilité des mises à jour du fichier par le réseau, du temps de traitement du fichier...
- Edité par dantonq 2 octobre 2017 à 21:45:11
Validez la réponse utile « Un problème clairement exposé est à moitié résolu. » Pas de MP technique
Le script suivant marche TANT QUE la commande exec est en fait un simple echo :
Ceci marche :
#!/bin/bash
#script à run en SUDO...
#Ce script permet de lancer récursivement les tâches présentes dans la TaskList.lst
todo=''
nlign=''
todo=$(grep -m1 "todo: " $1 | sed 's/todo: //g')
while [ true ] # "$todo" != ""
do
nlign=$(grep -nm1 todo: $1 | cut -d ':' -f1)
todo=$(grep -m1 "todo: " $1 | sed 's/todo: //g')
sed --in-place "$nlign""s/todo: /computing: /g" "$1"
echo $todo
#exec $todo
sed --in-place "$nlign""s/computing: /done: /g" "$1"
todo=$(grep -m1 "todo: " $1 | sed 's/todo: //g')
done
echo "No more tasks to do..."
Si on dé commente la ligne avec le exec, Alors, il exécute bien la première commande, et s’arrête aussi-tôt (retour au prompt).
J'ai testé avec ce script, le résultat est exactement le même (ok en echo, juste la première fonction si exec) :
#!/bin/bash
while true
do
nbL=$(awk '/^todo:/{print NR; exit}' $1)
((nbL)) || break
todo=$(grep -m1 "todo: " $1 | sed 's/todo: //g')
sed -i $nbL's/todo/running/' $1
echo "traitement ligne #$nbL en cours"
if exec $todo
then
sed -i $nbL's/running/done/' $1
else
sed -i $nbL's/running/failed/' $1
fi
done
Pourtant, dans les deux cas, nous ne sommes pas censés sortir de la boucle avant la dernière commande, qui est un "exit 0" (ou tant qu'il y a des "todo"). J'imagine que j'ai zappé un truc tout bête....
C'est normal que le script s'arrête, car la fonction exec remplace tout le code par ce qui est appelé par la fonction. Donc en clair, une fois que l'instruction exec est lue et interprêtée, bash considère que le script tout entier n'est plus que cette ligne de code.
Extrait de la page de man de exec (man 3 exec) :
The exec() family of functions replaces the current process image with a new process image.
C'est d'ailleurs pour ça que dans certains scripts de démarrage (.xinitrc), on demande d'écrire "exec <environnement_a_lancer>" tout à la fin du code, car de toute façon le reste ne s'exécutera jamais, même au retour de la fonction.
Pour exécuter le bout de code, essaie de le mettre entre `` (AltGr + 7)
Ah super, j'étais persuadé que c'était un truc du genre.... Mais j'ai pas eu le réflexe du man.
Comme tu l'as remarqué, dans mon script, la fonction est encapsulée dans une variable ; on verra si les `` fonctionnent. En tout cas, je sais où chercher du coup.
Effectivement, je ne sais pourquoi, je me suis entêté à ajouter un exec inutile... Malgré ça, le code continue son chemin, même si la fonction n'est pas terminée. Dans mon cas, le dd ne dure même pas 2*10^-4 secondes (et ne copie donc rien). Je pense que le "if" teste le lancement de la commande, mais pas son message de sortie.
Il faudrait que le script laisse la commande tourner tant qu'elle n'est pas finie....
On y est presque ! Mais j’avoue que contrairement à e que je pensais, mes compétences en Bash sont finalement assez minces pour ce genre de projet...
Je vous remercie donc beaucoup pour l'aide apportée !
peux-tu nous fournir une commande qui figure sur une ligne du fichier "todoList" ?
normalement, if vérifie le code de retour de la commande qui y est exécutée (c'est à ça qu'il sert !), et attend la fin de cette commande pour exécuter la suite des instructions then ou else.
Validez la réponse utile « Un problème clairement exposé est à moitié résolu. » Pas de MP technique
En ce qui concerne le if, c'est aussi ce que je pensais, mais dans mon cas, cela ne fonctionne pas.
Voici le script :
#!/bin/bash
while true
do
nbL=$(awk '/^todo:/{print NR; exit}' $1)
((nbL)) || break
todo=$(grep -m1 "todo: " $1 | sed 's/todo: //g')
sed -i $nbL's/todo/running/' $1
echo "traitement ligne #$nbL en cours"
if $todo
then
sed -i $nbL's/running/done/' $1
else
sed -i $nbL's/running/failed/' $1
fi
done
*le exit 0 est plus une sécurité pour le moment... Histoire d'être sure de sortir du script...
Et le résultat :
./newTM.sh TaskList.lst
traitement ligne #5 en cours
traitement ligne #6 en cours
ls: impossible d'accéder à '>>': Aucun fichier ou dossier de ce type
-rw-r--r-- 1 biokore biokore 0 oct. 8 19:38 tasktest.tst
traitement ligne #7 en cours
"plop" >> tasktest.tst
traitement ligne #8 en cours
0+0 enregistrements lus
0+0 enregistrements écrits
0 bytes copied, 0,00015342 s, 0,0 kB/s
traitement ligne #9 en cours
0+0 enregistrements lus
0+0 enregistrements écrits
0 bytes copied, 0,000145378 s, 0,0 kB/s
traitement ligne #10 en cours
traitement ligne #11 en cours
Voilà. A savoir, bien entendu, ces commandes ne seront pas les définitives, il s'agit simplement d'un test... Au final, il s'agira plutôt d'une centaine de commandes plus longues à traiter, sans nécessiter l'usage du disque ; mais tant qu'a faire, j'aimerais pouvoir le faire fonctionner avec tout type de commande.
Merci encore !
ps : petite précision, le fameux fichier "tasktest.tst" est bien créé, mais rien n'est écrit dedans.
je pense que le fichier existait avant l'exécution de la commande, car ls le liste.
il semble que le script fonctionne correctement : le ls échoue, et le exit fait s'achever le script. par contre, il sort avant que la dernière commande de modification du fichier soit exécutée ! mais c'est normal.
il faut donc exécuter les arguments comme s'il étaient une commande du shell avec eval (voir help eval).
if eval $todo; then ... fi
Validez la réponse utile « Un problème clairement exposé est à moitié résolu. » Pas de MP technique
Impeccable ! Avec "eval", tout passe exactement comme je le souhaitais.
Sujet résolu !
Merci à vous pour votre aide !
numéro de ligne variable et remplacement avec sed
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
Validez la réponse utile « Un problème clairement exposé est à moitié résolu. » Pas de MP technique
Validez la réponse utile « Un problème clairement exposé est à moitié résolu. » Pas de MP technique
Validez la réponse utile « Un problème clairement exposé est à moitié résolu. » Pas de MP technique
Validez la réponse utile « Un problème clairement exposé est à moitié résolu. » Pas de MP technique
Validez la réponse utile « Un problème clairement exposé est à moitié résolu. » Pas de MP technique
Validez la réponse utile « Un problème clairement exposé est à moitié résolu. » Pas de MP technique