Modifier un fichier texte avec awk en bash... (Mac)

Résolu/Fermé
MAMu_ Messages postés 48 Date d'inscription mercredi 3 avril 2013 Statut Membre Dernière intervention 25 mai 2013 - 3 avril 2013 à 16:02
dubcek Messages postés 18718 Date d'inscription lundi 15 janvier 2007 Statut Contributeur Dernière intervention 22 mars 2024 - 26 mai 2013 à 10:22
Bonjour, pour la réalisation d'un frontend pour MAME SDL au format Mac, en projo flash local, je cherche à modifier les fichiers de sorties de MAME en bash avec sed...

Mon fichier listfull.txt (mame -listfull > listfull.txt) en sortie de MAME se présente ainsi (le nombre d'espaces, remplacés ici par des _ pour une lecture plus proche de la réalité, entre les noms et les descriptions varient, mais le premier " est toujours le 19e charactere de la ligne...) :

Name:_____________Description:
005_______________"005"
10yard____________"10-Yard Fight (World, set 1)"
10yard85__________"10-Yard Fight '85 (US, Taito license)"
10yardj___________"10-Yard Fight (Japan)"

Mon but est de transformer donc ces lignes en :

cmd00001="005";
butt00001="005";
cmd00002="10yard";
butt00002="10-Yard Fight (World, set 1)";
cmd00003="10yard85";
butt00003="10-Yard Fight '85 (US, Taito license)";
etc...

De manière à pouvoir les injecter sous forme de variables dans Flash...
Et franchement, j'avoue avoir de sérieuses lacunes, balbutiant en bash et surtout découvrant sed, qui me semble être la bonne voie pour atteindre mon but...

D'avance merci, toutes aides, explications, solutions (voir autre methode*) seront les bienvenues...
* pas de php, uniquement qu'en bash, mon projet étant un frontend local et étant de plus limité également par ce qu'accepte de lancer flash localement via un bouton...)

Sincèrement, MAMu_
A voir également:

51 réponses

dubcek Messages postés 18718 Date d'inscription lundi 15 janvier 2007 Statut Contributeur Dernière intervention 22 mars 2024 5 615
27 avril 2013 à 11:37
essayer ce code f5.awk
l'odre des variables est celui de la variable v au début. à la place des print, on stocke dans un tableau, qu'on imprime à la fin de balise </game>
il suffit de changer cet ordre et de réexécuter
BEGIN {FS="[ \t>]+"; v="year|description|name|manufacturer|sourcefile|ismechanical|cloneof|type|rotate|width|height|status|emulation|color|sound|graphic" ; c="&"}
/<game |<display |<driver |<description>|<year>|<manufacturer>/ {gsub("\"", "");  gsub("%", "%%"); gsub("&", "and")}
/<game |<display |<driver / {for(f=2; f<=NF; f++)if($f ~ v){split($f, a, "="); t[a[1]]=$f}}
/<description>|<year>|<manufacturer>/ {split($0, a, "[<>]"); t[a[2]]=a[2] "=" a[3]}
/<\/game>/ {n=split(v, a, "[|=]"); for (m=1; m<=n; m++)if(t[a[m]])printf t[a[m]] c; print ""}
0
MAMu_ Messages postés 48 Date d'inscription mercredi 3 avril 2013 Statut Membre Dernière intervention 25 mai 2013
27 avril 2013 à 23:04
ok je viens d'essayer, merci ca marche, je recupere donc un fichier en sortie equivalent à l'ancien, mais avec year, description, name en premier...

"il suffit de changer cet ordre et de reexecuter..." ok :) mais je le change ou cet ordre...?

je suppose avec la ligne :
/<description>|<year>|<manufacturer>/ {split($0, a, "[<>]"); t[a[2]]=a[2] "=" a[3]}
...? mais je capte pas à quoi correspondent a2 et a3 sachant que dans l'ordre du code desc year manu, c'est a1 et a2 qui semblent pour moi être inversés lors de la sortie...
0
MAMu_ Messages postés 48 Date d'inscription mercredi 3 avril 2013 Statut Membre Dernière intervention 25 mai 2013
28 avril 2013 à 01:23
mais sachant que mon fichier en sortie commence maintenant toujours par :
year, description, name, manufacturer et sourcefile qui sont tous mes champs de "sort" possible qui m'interessent (sachant que de base il est deja "sort" par name...)

j'ai essayé
BEGIN {OFS='&'} { print $2,$1,$3,$4;$5 }' < variables.txt > description.txt
mais même en passant par un fichier externe -f order.awk dans lequel j'ai :
BEGIN {OFS='&'} { print $2,$1,$3,$4,$5 }

et j'obtiens comment dire euh... ^^ enfin voila quoi :)
0
dubcek Messages postés 18718 Date d'inscription lundi 15 janvier 2007 Statut Contributeur Dernière intervention 22 mars 2024 5 615
Modifié par dubcek le 28/04/2013 à 08:51
c'est la variable v qu'il faut changer:
v="year|description|name|manufacturer|sourcefile|ismechanical|cloneof|type|rotate|width|height|status|emulation|color|sound|graphic"
par ex.:
v="description|name|year|manufacturer|sourcefile|ismechanical|cloneof|type|rotate|width|height|status|emulation|color|sound|graphic"
et l'affichage se fera dans cet ordre
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
MAMu_ Messages postés 48 Date d'inscription mercredi 3 avril 2013 Statut Membre Dernière intervention 25 mai 2013
28 avril 2013 à 13:25
arf, trop bon ^^ merci
0
MAMu_ Messages postés 48 Date d'inscription mercredi 3 avril 2013 Statut Membre Dernière intervention 25 mai 2013
1 mai 2013 à 19:03
Bon avec la méthode du tableau, il y a un bug que je viens de découvrir... :/

je me retrouve avec des "cloneof=mariner", ou autre, ou encore "ismechanical=yes" un peu partout là ou il ne devraient pas y être...

Manifestement, à premiere vue, c'est partout ou les variables ne sont pas definies, il doit garder en memoire lors du awk avec le tableau la valeur precedente si celle ci n'est pas présente sur la ligne, mais pas à tout les coups, vu que je garde des "ismechanical=undefined", c'est donc que sur certaines lignes, il garde bien le fait que la variable n'est pas definie... :/ zarbe...

A part forcer l'ajout à chaque ligne des variables ismechanical=no, cloneof=--, etc... si l'entrèe n'est pas presente et ce, juste avant de rentrer les variables en memoire avant de construire le tableau, ou ajouter des exceptions..., je ne vois pas comment faire...

d'ailleurs, meme si je "crois comprendre" d'ou vient le bug et que j'imagine comment réussir à le contourner, l'appliquer, c'est une autre histoire... :/

je crois que les variables possibles qui peuvent être non présentes sur chaque ligne et donc non définies, et donc qui peuvent engendrer le bug, sont : ismechanical, cloneof, type, rotate, width et height...

Dubcek, sincèrement désolé de te prendre encore la tête sur ce même problème... :/

PS: j'ai vérifié, avant la methode du tableau, le bug n'etait pas present et les variables non présentes sur chaque lignes m'affichaient bien "undefined" dans flash lors de l'import...
0
MAMu_ Messages postés 48 Date d'inscription mercredi 3 avril 2013 Statut Membre Dernière intervention 25 mai 2013
1 mai 2013 à 19:19
(le cloneof=mariner par exemple est present sur l'entree de 88games, qui est pourtant un parent, et non pas un clone...)
0
MAMu_ Messages postés 48 Date d'inscription mercredi 3 avril 2013 Statut Membre Dernière intervention 25 mai 2013
1 mai 2013 à 19:15
peut etre en forcant la valeur des variables qui peuvent être non définies à "--" avant même d'analyser la ligne et de construire le tableau..? comme ca si la variable n'est pas definie sur une ligne, elle garde la valeur "--" et non pas la valeure de la ligne precedente, et si elle est definie, la valeur "--" serait automatiquement substituée par la bonne variable si celle ci est presente sur la ligne...

non...?
0
dubcek Messages postés 18718 Date d'inscription lundi 15 janvier 2007 Statut Contributeur Dernière intervention 22 mars 2024 5 615
2 mai 2013 à 08:15
ton analyse est correcte, j'ai donc rajouté un delete t pour que le tableau soit effacé à chaque debut de balise <game, ajouter cette ligne :
BEGIN...
/<game / {delete t}
/<game |<display |<driver / {for(f=2; f<=NF; f++)if($f ~ v){split($f, a, "="); t[a[1]]=$f}}
...
0
MAMu_ Messages postés 48 Date d'inscription mercredi 3 avril 2013 Statut Membre Dernière intervention 25 mai 2013
2 mai 2013 à 11:23
Et là j'ai envie dé té dire "BENCO" :)

A l'air de marcher nickel ^^ je vais tout bien verifier, mais à premiere vue tout est parfait :)

Toujours le même nombre de lignes, les undefined sont bien undefined...

Encore une fois un grand merci à toi :)
0
MAMu_ Messages postés 48 Date d'inscription mercredi 3 avril 2013 Statut Membre Dernière intervention 25 mai 2013
25 mai 2013 à 16:58
Désolé dubcek, je reviens une nouvelle fois vers toi...

Mon code s'est bien agrandi et étoffé... cependant, lorsque je change l'ordre des valeurs dans f5.awk, par exemple v="name|description..." au lieu de v="description|name...", les fichiers obtenus n'ont plus la même taille à quelques octets près...

Je suppose donc qu'il persiste une erreur quelques part... et c'est lors du num2.awk que j'ai légèrement modifié... donc errare humanum est, mais l'errare doit venir de moi ^^

Pour le verifier, j'ai créé deux fichier awk, f6 et f7.awk et je les applique l'un après l'autre toujours sur mame.xml en modifiant le nom en sortie...:

Mon fichier batch (msdos) :

echo Create listfull.xml
mame -listxml > listfull.xml
echo Extract variables.txt
awk -f f7.awk listfull.xml > 0variables.txt
awk -f f8.awk listfull.xml > 1variables.txt

echo extract nbre de ligne
echo mamenf= > mamenf.txt
grep -c name= 0variables.txt >> mamenf.txt
sed -i.BAK ":z;N;s/\n//;bz" mamenf.txt
sed -i "s/ //g" mamenf.txt
sort 0variables.txt > a0
awk -f num2.awk a0 > 0variables.txt
sed "" mamenf.txt >> 0variables.txt

echo extract nbre de ligne
echo mamenf= > mamenf.txt
grep -c name= 1variables.txt >> mamenf.txt
sed -i.BAK ":z;N;s/\n//;bz" mamenf.txt
sed -i "s/ //g" mamenf.txt
sort 1variables.txt > a0
awk -f num2.awk a0 > 1variables.txt
sed "" mamenf.txt >> 1variables.txt


f7.awk :
BEGIN {FS="[ \t>]+"; v="description|name|manufacturer|year|sourcefile|ismechanical|cloneof|type|rotate|width|height|status|emulation|color|sound|graphic" ; c="&"}
/<game |<display |<driver |<description>|<year>|<manufacturer>/ {gsub("\"", "");  gsub("%", "%%"); gsub("&", "and")}
/<game / {delete t}
/<game |<display |<driver / {for(f=2; f<=NF; f++)if($f ~ v){split($f, a, "="); t[a[1]]=$f}}
/<description>|<year>|<manufacturer>/ {split($0, a, "[<>]"); t[a[2]]=a[2] "=" a[3]}
/<\/game>/ {n=split(v, a, "[|=]"); for (m=1; m<=n; m++)if(t[a[m]])printf t[a[m]] c; print ""}


f8.awk :
BEGIN {FS="[ \t>]+"; v="name|description|manufacturer|year|sourcefile|ismechanical|cloneof|type|rotate|width|height|status|emulation|color|sound|graphic" ; c="&"}
/<game |<display |<driver |<description>|<year>|<manufacturer>/ {gsub("\"", "");  gsub("%", "%%"); gsub("&", "and")}
/<game / {delete t}
/<game |<display |<driver / {for(f=2; f<=NF; f++)if($f ~ v){split($f, a, "="); t[a[1]]=$f}}
/<description>|<year>|<manufacturer>/ {split($0, a, "[<>]"); t[a[2]]=a[2] "=" a[3]}
/<\/game>/ {n=split(v, a, "[|=]"); for (m=1; m<=n; m++)if(t[a[m]])printf t[a[m]] c; print ""}


et enfin mon num2.awk :
{gsub("%", "%%"); ns=sprintf(++n); gsub("=", ns "="); printf $0} 


(j'ai modifié ns=sprintf("%05d", ++n); par ns=sprintf(++n); car je n'ai plus besoin d'avoir des 00001,00002, etc... les fichiers en sortie se chargent donc plus rapidement car plus legers...)



Donc aprés avoir lancé ceci j'obtiens :
0variables.txt 7893ko
1variables.txt 7884ko

NB : si je mets une pause juste apres f7 et f8.awk, les fichiers ont bien la même taille... Il me semble donc evident que c'est lors du num2.awk qu'il y a une erreur... si je reprends le num.awk d'origine, les fichiers ont bien la même taille en sortie.... L'ajout de la ligne mamenf en fin de fichier étant identiques dans les deux cas... :/

Si tu as la moindre idée, ou qqn d'autre...
0
MAMu_ Messages postés 48 Date d'inscription mercredi 3 avril 2013 Statut Membre Dernière intervention 25 mai 2013
25 mai 2013 à 22:58
Bon après m'être pris la tête, je pense en fait que le bug est.. qu'il n'y a pas de bug... ^^ C'est logique... la taille peut differer après la numerotation... justement car il n'y a plus les 0000... donc si une ligne avec beaucoup de variables etait en 10eme rangée avant le sort, mais qu'apres le sort elle se retrouve en 28000 position, sa ligne sera donc plus grande... donc le fichier sera forcemment plus lourd... CQFD... si j'avais gardé les "0000", chaque numerotation prendrait exactement le même nombre d'octets quelle que soit sa position.... :)
0
dubcek Messages postés 18718 Date d'inscription lundi 15 janvier 2007 Statut Contributeur Dernière intervention 22 mars 2024 5 615
26 mai 2013 à 10:22
effectivement, 00001 prend la même taille que 09999
0