#1 Le 21/05/2006, à 13:26
- hector
script bash pour bidouiller un fichier texte
Bonjour,
j'essaie de mettre quelques listes de dictionnaires (lexique plutôt) au format stardict. Pour celà j'ai de grands fichiers textes que j'aimerais gérer automatiquement.
Par exemple
pour chaque ligne, j'ai :
1/ un mot (m1)
2/ un "tab" ( \t )
3/ un autre mot (m2)
j'aimerais pouvoir retourner afin d'avoir d'abord le mot 2 puis le tab , puis le mot1. mais le faire à la main est impossible vu le nombre de lignes du texte.
J'aimerais me faire un petit script bash qui ferait ça mais je n'y connais rien, auriez vous quelques idées , des noms de commande?
à moins qu il n'existe un éditeur qui permet ce genre de choses ..
Merci
nb: l'idée est de contribuer à mettre à disposition des dictionnaires libres au format stardict (logiciel libre), car de ce point de vue le libre a pas mal de retard ...
Dernière modification par hector (Le 20/09/2007, à 00:07)
Hors ligne
#2 Le 21/05/2006, à 16:04
- hello_world
Re : script bash pour bidouiller un fichier texte
salut!
Je n'ai jamais touché au bash (si en fait, l'autre jour j'ai fait un scripte pour faire tourner un progamme plusieurs fois de suite, et je crois même avoir fait un hello word... "echo hello word"... ct dure ;-) ). Par contre j'ai fait recement un programme en c++ qui remplaçait des chaines de charactères. J'ai essayé de l'adapter pour ton cas et ça marche. Mais il n'est pas très solide vu que je l'ai fait un peu rapidement. Il faudrait que je voie exactement tes fichiers pour voir si il fonctionne. Donc si ça t'interesse, redilemele ;-)
++
Hors ligne
#3 Le 21/05/2006, à 18:46
- hector
Re : script bash pour bidouiller un fichier texte
bien sûr que ça m'intéresse!
ici
Merci!
Dernière modification par hector (Le 21/05/2006, à 18:47)
Hors ligne
#4 Le 21/05/2006, à 18:53
- jr95
Re : script bash pour bidouiller un fichier texte
En regardant du coté de sed et des expressions régulières (qui sont quasiment les mêmes que celles de ed) on trouve que
sed -e 's/\(.*\)\t\(.*\)/\2\t\1/' fichier1 > fichier2
fait ce que tu désires.
Tu pourras trouver plus d'informations dans les pages de man de sed et ed.
Hors ligne
#5 Le 21/05/2006, à 20:35
- hello_world
Re : script bash pour bidouiller un fichier texte
C'est bien ce que je pensais... un peu trop compliqué pour mon code actuel.... Je n'avais pas prévu des m2 du genre "crochet en bois pouvant servir à la cueillette des fruits". Je vais voir si je peux améliorer ça. Je te tiens au courant. Sinon, est-ce seulement chez moi que les accents et autres ne passent pas?
++
Hors ligne
#6 Le 21/05/2006, à 21:56
- hector
Re : script bash pour bidouiller un fichier texte
les accents je crois que c'est à cause du serveur. Sinon les quelques phrases pour m2 sont minoritaires, et je devrai les refaire à la main de toute façon.
je vais regarder sed aussi, ça a l'air intéressant ...
Dernière modification par hector (Le 21/05/2006, à 21:57)
Hors ligne
#7 Le 21/05/2006, à 22:12
- hector
Re : script bash pour bidouiller un fichier texte
La commande de jr95 marche nickel, merci! (pas encore tout compris la syntaxe par contre ...)
merci aussi à hello_world pour ses recherches. j'aurai peut etre d'autres requêtes bientôt ...
Hors ligne
#8 Le 22/05/2006, à 06:50
- jr95
Re : script bash pour bidouiller un fichier texte
Voici une petite explication sur la syntaxe de la commande sed.
\t correspond à la tabulation
.* correspond à n'importe quelle suite de caractère
Les \( et \) permettent de mémoriser la chaine contenue entre et de la réutiliser dans la 2ème partie de la substitution sous la forme \1 (ou \2 ou \3 ...)
Il y a des explications plus détaillées dans le man de ed.
Hors ligne
#9 Le 22/05/2006, à 10:44
- hector
Re : script bash pour bidouiller un fichier texte
Merci!
j'essaie maintenant de classer les lignes par ordre alphabétique ...
j'ai pas envore vu ça dans le man ed ... mais j'y retourne ...
Hors ligne
#10 Le 22/05/2006, à 11:02
- jr95
Re : script bash pour bidouiller un fichier texte
Pour le tri, ed ou sed ne peuvent pas grand chose, mais par contre la commande 'sort' est là pour cela.
En faisant quelque chose du style
sed -e 's/\(.*\)\t\(.*\)/\2\t\1/' fichier1 | sort options_qui_vont_bien > fichier2
tu devrais à faire ce que tu veux.
Pour les options de sort, je te laisses choisir parmi les nombreuses possibilités.
Hors ligne
#11 Le 22/05/2006, à 12:02
- hector
Re : script bash pour bidouiller un fichier texte
Excellent!
trop fort ces lignes de commande! (et ce jr95 )
sort -t \n tesf.tab > test2.tab
Hors ligne
#12 Le 08/09/2007, à 08:53
- Sorbus
Re : script bash pour bidouiller un fichier texte
Bonjour,
Je reprends ce vieux fil... qui est toujours d'actualité !
Avec les éléments donnés jusque là dans ce fil, on peut créer un script "inversdic.sh" avec le contenu suivant :
#!/bin/bash
TEMP=`mktemp`
> $2
cat $1 | sed -e 's/\(.*\)\t\(.*\)/\2\t\1/' > $TEMP
sort -t \n $TEMP > $2
rm $TEMP
Il suffit ensuite de lancer
./inversdic.sh fichier_source.tab fichier_cible.tab
pour obtenir l'autre sens du dictionnaire.
J'aimerais essayer d'aller un peu plus loin.
Souvent, un mot dans une langue est traduit par plusieurs mots dans une autre.
... et inversement, un mot de l'autre langue correspond à plusieurs mots de la première.
Dans un dico électronique, cela est généralement signifié par des virgules dans la 2ème colonne (2ème champ) qui correspond à la traduction du mot de la 1ère colonne.
Exemple :
abbacchià demeurer bouche bée
abbachjà aboyer, demeurer bouche bée
abbacinà avoir le vertige, faire tourner la tête, ébloulir
abbaghjà aboyer
abbaglianà avoir le vertige
abbalanà avoir le regard troublé
abbambacinà avoir le vertige
abbambanà avoir le vertige
abbandonu abandon
inversé avec inversdict.sh donne ceci :
abandon abbandonu
aboyer, demeurer bouche bée abbachjà
aboyer abbaghjà
avoir le regard troublé abbalanà
avoir le vertige abbaglianà
avoir le vertige abbambacinà
avoir le vertige abbambanà
avoir le vertige, faire tourner la tête, ébloulir abbacinà
demeurer bouche bée abbacchià
Comment faire pour :
1°) d'une part regrouper les entrées identiques de la première colonne... et pour mettre en correspondance sur la même ligne, séparés d'une virgule, les divers mots correspondants, dans la 2ème colonne (dans l'exemple "avoir le vertige" sur une seule ligne, avec ses traductions
2°) d'autre part séparer en deux lignes les mots séparés par une virgule dans le 1er champ (exemple "aboyer, demeurer bouche bée"... pour en faire deux entrées de la langue à traduire... avec en face de chacune des nouvelles entrées le même mot (ici "abbachjà")
C'est à dire pour obtenir ceci au final :
abandon abbandonu
aboyer abbachjà, abbaghjà
avoir le regard troublé abbalanà
avoir le vertige abbaglianà, abbambacinà, abbambanà, abbacinà
demeurer bouche bée abbacchià, abbachjà
ébloulir abbacinà
faire tourner la tête abbacinà
L'application du script modifié à ce dernier fichier.tab devant redonner le fichier original...
Hors ligne
#13 Le 09/09/2007, à 23:39
- hector
Re : script bash pour bidouiller un fichier texte
Ayant eu 6 heures de train à passer, j'ai essayé d'écrire un script pour ton 2ème truc.
Mais je ne suis pas un pro et n'ai pas pu le tester -plus d'ubuntu jusqu'au week end prochain-, donc autant dire que ça ne marchera pas.
mais si ça peut encourager d'autres... sinon je tenterai de l'améliorer dans les prochains jours...
il est juste censé transformer:
abandon abbandonu
aboyer, demeurer bouche bée abbachjà
aboyer abbaghjà
avoir le regard troublé abbalanà
avoir le vertige abbaglianà
avoir le vertige abbambacinà
avoir le vertige abbambanà
avoir le vertige, faire tourner la tête, ébloulir abbacinà
demeurer bouche bée abbacchià
en
abandon abbandonu
aboyer abbachjà
demeurer bouche bée abbachjà
aboyer abbaghjà
avoir le regard troublé abbalanà
avoir le vertige abbaglianà
avoir le vertige abbambacinà
avoir le vertige abbambanà
avoir le vertige abbacinà
faire tourner la tête abbacinà
ébloulir abbacinà
demeurer bouche bée abbacchià
je mets en commentaire ce que c'est censé faire...
Nligne=$(cat $1 | wc -l) #nombre de ligne
for j in $(seq 1 $Nligne) #pour chaque ligne...
ligne= $(cat $1 | head -n $j | tail -n 1) #je nomme la ligne
Nocc= $( cat $ligne |cut -d'\t' -f1 | tr ',' '\n' | wc -l ) #)je compte le nbre d'occurences (séparé par des virgules
if [ $Nocc gt 1 ]; then #si ce nbre d'occurence est supérieur strict à 1
exp2= $(cat $ligne | cut -d'\t' -f2) #définition
for i in $(seq 1 $Nocc); do #alors pour chaque occurence
exp1=$(cat $ligne | cut -d'\t' -f1| cut -d',' -f$i) #ième occurence
nouvelleligne=$exp1"\t"$exp2 #nouvelle ième ligne
echo $nouvelleligne >> $2 #je la rajoute à la fin de mon fichier $2
done
else # sinon (nb occurences =1),
echo $ligne >> $2 #je copie tel quel ma ligne dans $2
fi
done
Dernière modification par hector (Le 10/09/2007, à 00:27)
Hors ligne
#14 Le 10/09/2007, à 01:35
- best_friend_fr
Re : script bash pour bidouiller un fichier texte
awk -F"\t" '{split($2,tab,", ");for (i in tab) print tab[i]"\t"$1}'
Salut
Cette ligne te fait l'etape 2 et l'inversion des colonnes.
Il reste a trier ( avec sort) et a regrouper les lignes
Dernière modification par best_friend_fr (Le 10/09/2007, à 01:36)
sudo apt-get replace langage_sms by grammaire orthographe ponctuation
La documentation est avant tout faite pour ceux qui posent les questions, et non ceux qui y répondent
Best_friend_fr
Hors ligne
#15 Le 10/09/2007, à 02:11
- best_friend_fr
Re : script bash pour bidouiller un fichier texte
En gros, un truc du genre me semble pas mal.
Il doit y avoir plus simple, en faisant le tri directement dans awk, mais je sais pas le faire.
#!/bin/bash
cat $1 | awk -F"\t" '{split($2,tab,", ");for (i in tab) print tab[i]"\t"$1}' |
sort -t \n |
awk -F"\t" '{if ($1 != key) {if (paspremier == "oui") printf "\n"; printf $1"\t"$2;} else {printf ", "$2;} key = $1; paspremier="oui";}' > $2
echo >> $2
La derniere ligne est juste parce que j'ai la flemme de trouver comment ajouter un retour a la ligne, mais pour que ca soit plus beau, tu peux t'amuser a chercher.
sudo apt-get replace langage_sms by grammaire orthographe ponctuation
La documentation est avant tout faite pour ceux qui posent les questions, et non ceux qui y répondent
Best_friend_fr
Hors ligne
#16 Le 10/09/2007, à 02:21
- best_friend_fr
Re : script bash pour bidouiller un fichier texte
En fait, c'etait tout con
#!/bin/bash
cat $1 | awk -F"\t" '{split($2,tab,", ");for (i in tab) print tab[i]"\t"$1}' |
sort -t \n |
awk -F"\t" '{if ($1 != key) {if (paspremier == "oui") printf "\n"; printf $1"\t"$2;} else {printf ", "$2;} key = $1; paspremier="oui";} END {printf("\n");}' > $2
sudo apt-get replace langage_sms by grammaire orthographe ponctuation
La documentation est avant tout faite pour ceux qui posent les questions, et non ceux qui y répondent
Best_friend_fr
Hors ligne
#17 Le 10/09/2007, à 07:34
- Sorbus
Re : script bash pour bidouiller un fichier texte
super best_friend_fr...
... je cherchais aussi de mon côté depuis samedi... et j'avais progressé un peu, mais sans aboutir.
Il reste juste une bricole; dans le fichier destination obtenu avec ce script, j'ai ça :
avoir le vertige abbacinà
avoir le vertige abbaglianà, abbambacinà, abbambanà
c'est à dire qu'il y a 4 mots traduisant "avoir le vertige", et seulement trois sont regroupés sur la même ligne.
Un essai sur un autre bout de texte me donne au final quelque chose de bon, avec juste une petite inversion alphabétique dans le fichier final ("structurer" avant "structure")... mais ça, je pense que c'est facile à régler en rajoutant un "sort -t \n" à la fin du script...
Voilà... je vais tester sur une liste plus longue. Et essayer de comprendre le script.
Merci
P.S. : hector, j'ai testé ta proposition, mais j'ai une erreur dans le terminal
"line 3: erreur de syntaxe près du jeton `ligne=$(cat $1 | head -n $j | tail -n 1)' inattendu
(line 3: ` ligne=$(cat $1 | head -n $j | tail -n 1) #je nomme la ligne)"
De mon côté, j'étais aussi parti avec sed pour réaliser en premier l'étape 2... mais je bloquais pour récupérer un mot dans le 2ème champ d'une ligne pour le placer dans le 2ème champ (vide) de la ligne en-dessus.
Dernière modification par Sorbus (Le 10/09/2007, à 08:13)
Hors ligne
#18 Le 10/09/2007, à 08:26
- best_friend_fr
Re : script bash pour bidouiller un fichier texte
Salut
Bizarre qu'il en regroupe que 3... Tu es sur que tu as toujours des tab entre les colonnes, et que tu as pas un espace mal place (genre un "avoir le vertige " au lieu de "avoir le vertige" ?)
Pour l'ordre alphabetique, ca doit venir du fait que le code ascii de la tabulation est apres les lettres. Je te laisse etudier ca.
Enfin, je pense que tu comprendras plus facilement awk que sed. Si vraiment tu veux t'amuser, sache qu'on peut aussi utiliser les regexp dans awk et donc rendre ca totalement illisible.
Allez, a plus
sudo apt-get replace langage_sms by grammaire orthographe ponctuation
La documentation est avant tout faite pour ceux qui posent les questions, et non ceux qui y répondent
Best_friend_fr
Hors ligne
#19 Le 10/09/2007, à 08:57
- Sorbus
Re : script bash pour bidouiller un fichier texte
et que tu as pas un espace mal place (genre un "avoir le vertige " au lieu de "avoir le vertige" ?)
C'est ça... enfin, plutôt, c'est l'inverse. En fait, dans le fichier d'origine, j'ai l'impression que toutes les lignes sont terminées par un espace (inutile)... Il faudrait donc supprimer tous les espaces qui sont en fin de ligne avant d'appliquer ton script.
Le "avoir le vertige" qui reste à part dans le fichier final obtenu avec ton script est celui qui est dans la ligne "abbacinà avoir le vertige, faire tourner la tête, ébloulir ", donc juste avant une virgule.
J'ai placé ça en tête du script pour éliminer les espaces de fin de ligne :
TEMP=`mktemp`
> $2
cat $1 | sed 'N;s/ \n/\n/g;P;D;' > $TEMP
mv $TEMP $2
... et ça a l'air tout bon.
Il reste la question de l'ordre alphabétique. Je pense que le problème vient du fait que la tabulation (séparant les deux champs) n'est pas prise en compte par les options utilisées pour la mise en ordre alphabétique dans nos scripts. Dans l'exemple :
structurer structurà
structure structura
structurerstructurà
est logiquement placé avant
structurestructura
Avec sort -t \n il y a un autre problème d'ordre alphabétique sur le premier champ lorsqu'il y a une expression formée de plusieurs mots. Dans ce cas, c'est parce qu'un espace n'est pas pris en compte comme un caractère (à placer dans l'ordre alphabétique avant tout autre caractère) :
"a vi discurrite?"
qui devrait être placé avant
"abambana"
est placé après
"avè"
Ce problème demeure. Il reste donc a trouver la méthode :
1°) pour faire en sorte que pour l'ordre alphabétique, ne soit pris en compte que le premier champ - c'est à dire seulement ce qui est avant la tabulation - tout en gardant bien sûr la ligne entière (il ne faudrait pas déplacer par ordre alphabétique le 1er champ seulement sans que le second suive... tout serait faussé).
2°) pour que au final "a u" soit avant "ab" (c'est à dire que l'espace soit pris en compte).
Dernière modification par Sorbus (Le 10/09/2007, à 14:04)
Hors ligne
#20 Le 10/09/2007, à 17:50
- best_friend_fr
Re : script bash pour bidouiller un fichier texte
"a vi discurrite?"
qui devrait être placé avant
"abambana"
est placé après
"avè"
Hmm, es tu sur ?
En francais, l'espace est neutre, il ne compte pas comme un caractere.
L'ordre alphabetique est donc bien
"abambana"
"avè"
"a vi discurrite?"
Tu as une solution pour faire ca avec un programme awk.
Tu mets ta premiere colonne dans un tableau, ta deuxieme colonne dans un autre tableau, et tu tries le premier en recuperant les indices. Comme ca, tu peux garder la liaison entre les 2 tableaux.
sudo apt-get replace langage_sms by grammaire orthographe ponctuation
La documentation est avant tout faite pour ceux qui posent les questions, et non ceux qui y répondent
Best_friend_fr
Hors ligne
#21 Le 10/09/2007, à 18:09
- Sorbus
Re : script bash pour bidouiller un fichier texte
En francais, l'espace est neutre, il ne compte pas comme un caractere.
Tu as raison !
J'essayais bêtement de suivre l'ordre proposé par un dictionnaire en ligne... mais ce n'est pas le bon. Il suffit de voir où est placé "a priori" dans un dictionnaire français !
Ce problème n'en est donc plus un...
Il ne reste donc plus que celui du tri opéré seulement sur le 1er champ... je vais essayer ta proposition avec awk... mais il faut que je comprenne comment on fait pour récupérer les indices...
Hors ligne
#22 Le 10/09/2007, à 18:40
- best_friend_fr
Re : script bash pour bidouiller un fichier texte
2 solutions:
1 Regarder du cote de asorti()
2 Faire avant un sed qui remplace tout les tab par un caractere place avant en ascii.
sudo apt-get replace langage_sms by grammaire orthographe ponctuation
La documentation est avant tout faite pour ceux qui posent les questions, et non ceux qui y répondent
Best_friend_fr
Hors ligne
#23 Le 10/09/2007, à 19:47
- Sorbus
Re : script bash pour bidouiller un fichier texte
Merci pour l'idée... J'ai utilisé la solution 2, et ça marche... même si je ne sais pas quel est le premier caractère dans l'ordre de classement par "sort". J'ai utilisé le zéro, en estimant qu'aucun mot ne doit comporter un zéro dans son écriture, ni à la fin...
TEMP=`mktemp`
> $2
cat $1 | sed 's/\t/00000/g' > $TEMP
mv $TEMP $2
cat $2 | sort -t \n > $TEMP
mv $TEMP $2
cat $2 | sed 's/00000/\t/g' > $TEMP
mv $TEMP $2
Je teste le l'ensemble du script avec cet ajout sur un fichier de 2000 mots, et je donne des nouvelles.
@+
Hors ligne
#24 Le 11/09/2007, à 04:56
- best_friend_fr
Re : script bash pour bidouiller un fichier texte
Hmm, je te deconseille l'utilisation du caractere 0, utilise pour d'autre choses par le systeme (fin de chaines...) Prends en plutot un autre.
Edit:
J'ai peut etre mal compris. Tu rajoute le caractere 0 ou des "0" ? si c'est des "0", ca me choque pas.
Dernière modification par best_friend_fr (Le 11/09/2007, à 04:57)
sudo apt-get replace langage_sms by grammaire orthographe ponctuation
La documentation est avant tout faite pour ceux qui posent les questions, et non ceux qui y répondent
Best_friend_fr
Hors ligne
#25 Le 11/09/2007, à 08:07
- Sorbus
Re : script bash pour bidouiller un fichier texte
Je rajoute cinq "0" (chiffre zéro)... mais je peux en mettre un autre à la place si c'est mieux, pourvu que ce soit classé avant "a" dans le tri effectué par "sort".
J'ai fait le test du script sur un fichier de 2000 entrées. Le conversion dans l'autre sens de la langue a été presque instantanée, mais correcte, sauf pour cinq entrées qui utilisaient la virgule autrement que comme séparant deux mots (traductions) distincts, du type de cet exemple fictif :
abughjà prendre, avec délicatesse, quelque chose
L'utilisation du script suppose donc une certaine vigilance pour respecter une syntaxe dans le fichier source... J'ai remplacé les cinq entrées concernées en éliminant les virgules dans ces cas. Et le script fonctionne parfaitement.
Merci à tous, et en particulier à best_friend_fr...
... et je laisse le soin à hector de marquer ce sujet comme "résolu"...
... même si je garderai un oeil sur ce fil au cas ou des améliorations soient proposées.
@+
Dernière modification par Sorbus (Le 11/09/2007, à 08:07)
Hors ligne