Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 26/01/2014, à 22:37

Jean-paul 3

Subtitution de donnée fichier A vers fichier B

bonjour,

j'ai a substituer une donnée par une autre sur un simple fichier texte où le séparateur est un "|".

exemple du fichier où effectuer la substitution :

donnée1A|donnée1B|donnée1C|donnée1D|donnée1E|donnée1F|
donnée2A|donnée2B|donnée2C|donnée2D|donnée2E|donnée2F|
donnée3A|donnée3B|donnée3C|donnée3D|donnée3E|donnée3F|
donnée4A|donnée4B|donnée4C|donnée4D|donnée4E|donnée4F|
......

et bien entendu, je possède un second fichier où se trouve la substitution

donnée1E|donnée1E de substitution
donnée2E|donnée2E de substitution
donnée3E|donnée3E de substitution
donnée4E|donnée4E de substitution
......

Un collègue m'a montré comment effectuer cette substitution par un "rechercheV" dans Excel, mais je me doute qu'il doit être possible d'obtenir le même résultat par le terminal !
Les véritables fichiers font plusieurs milliers de lignes

Une âme charitable peut-elle me conseiller une commande.
D'avance Merci à celui (ou celle) qui pourra m'aider smile

Hors ligne

#2 Le 26/01/2014, à 23:27

pingouinux

Re : Subtitution de donnée fichier A vers fichier B

Bonsoir,
En appelant f1 et f2 les deux fichiers :

sed -f <(sed 's/^/s|/;s/$/|/' f2) f1

Ce qui donne :

donnée1A|donnée1B|donnée1C|donnée1D|donnée1E de substitution|donnée1F|
donnée2A|donnée2B|donnée2C|donnée2D|donnée2E de substitution|donnée2F|
donnée3A|donnée3B|donnée3C|donnée3D|donnée3E de substitution|donnée3F|
donnée4A|donnée4B|donnée4C|donnée4D|donnée4E de substitution|donnée4F|

Hors ligne

#3 Le 27/01/2014, à 05:56

nesthib

Re : Subtitution de donnée fichier A vers fichier B

Attention, la solution de pingouinux est astucieuse, courte, mais absolument non idéale d'un point de vue algorithmique.
Quelle est la taille de chaque fichier (en terme de lignes) ?
S'ils sont vraiment gros, le double sed imbriqué va être limité par le fait que le premier fichier doit être parcouru entièrement pour chaque ligne du second (sans parler des accès disque). Dans ce cas il faut se tourner vers une solution un peu plus complexe à mettre en œuvre mais plus économique. Par exemple parcourir chaque ligne une seule fois, comparer le cinquième terme avec un dictionnaire des substitutions.

une façon de faire en python :

#!/usr/bin/python
import sys
substitution = {}

if not len(sys.argv) == 3:
    print('usage: %s <input_file> <substitutions_file>' % sys.argv[0])
    exit

with open(sys.argv[2], 'r') as f:
    for line in f.xreadlines():
        (a,b) = line[:-1].split('|', 1)
        substitution[a] = b

with open(sys.argv[1], 'r') as f:
    for line in f.xreadlines():
        split_line = line[:-1].split('|')
        try:
            split_line[4] = substitution[split_line[4]]
            print('|'.join(split_line))
        except KeyError:
            print(line[:-1])

Pour lancer le script (à rendre exécutable) :

./script.py fichier_source fichier_substitutions

Et pour exporter vers un fichier

./script.py fichier_source fichier_substitutions >fichier_sortie

Pour un fichier de 100 000 lignes avec 1 000 lignes de substitutions, la solution de pingouinux a besoin de 15 secondes alors que la mienne est instantanée. En passant à 10 000 substitutions, la solution avec sed mouline pendant 20 minutes, celle en python nécessite environ un dixième de seconde. À 1 millions de lignes et 10 000 substitutions je n'ai testé que ma solution, elle réussit en environ 1,4 secondes wink

NB. pour générer des fichiers de test :

rm /tmp/fichier_substitutions 2>/dev/null ; for i in {0..9999} ; do echo "orig$i|sub$i" >>/tmp/fichier_subtitutions ; done
rm /tmp/fichier_source 2>/dev/null ; for i in {0..99999} ; do echo "${RANDOM}|${RANDOM}|${RANDOM}|${RANDOM}|orig$((RANDOM%999))|${RANDOM}|" >>/tmp/fichier_source ; done

NB2. si les fichiers sont vraiment énormes (ex. plusieurs gigas de données), il est possible que la mémoire vive soit limitante. Il faudrait alors modifier le script python pour qu'il enregistre les substitution au fur et à mesure dans le fichier de sortie, au lieu de les envoyer sur la sortie standard.


GUL Bordeaux : GirollServices libres : TdCT.org
Hide in your shell, scripts & astuces :  applications dans un tunnelsmart wgettrouver des pdfinstall. auto de paquetssauvegarde auto♥ awk
  ⃛ɹǝsn xnuᴉꞁ uʍop-ǝpᴉsdn

Hors ligne

#4 Le 27/01/2014, à 08:58

pingouinux

Re : Subtitution de donnée fichier A vers fichier B

Je confirme l'analyse de nesthib. De plus, ma solution cherchait la chaîne à remplacer sur les lignes entières, et non uniquement dans le 5ème champ.

Hors ligne

#5 Le 27/01/2014, à 09:24

Jean-paul 3

Re : Subtitution de donnée fichier A vers fichier B

Merci à Pingouinux et Nesthib pour vos réponses,

Mon fichier à modifier devrait représenter environ 200 000 lignes, je dois le recevoir en fin de semaine.

Je teste vos 2 solutions (je connais un peu Sed mais pas Python) et reviens vers nous  smile

Bonne journée à vous !

Hors ligne

#6 Le 27/01/2014, à 11:07

pingouinux

Re : Subtitution de donnée fichier A vers fichier B

Voici une solution avec awk, pas aussi performante que celle de nesthib, mais assez honorable quand même (1 million de lignes, 10 000 substitutions : 2,3 secondes pour ma solution, 1,7 pour celle de nesthib #3)

awk -F"|" -v OFS="|" '
{ if(FNR==NR) {substit[$1]=$2}
  else { if(substit[$5]) $5=substit[$5]; print $0}
}
' "$2" "$1"

À appeler ainsi :

./script_awk fichier_source fichier_substitutions

Hors ligne

#7 Le 28/01/2014, à 02:43

nesthib

Re : Subtitution de donnée fichier A vers fichier B

@Jean-paul 3 : N'hésite pas à demander si tu veux que l'on commente nos solutions ou que l'on t'aide à les personnaliser wink


GUL Bordeaux : GirollServices libres : TdCT.org
Hide in your shell, scripts & astuces :  applications dans un tunnelsmart wgettrouver des pdfinstall. auto de paquetssauvegarde auto♥ awk
  ⃛ɹǝsn xnuᴉꞁ uʍop-ǝpᴉsdn

Hors ligne

#8 Le 02/02/2014, à 22:09

Jean-paul 3

Re : Subtitution de donnée fichier A vers fichier B

Bonjour à vous,

voici mon retour comme promis,
les 2 scripts de Pingouinux ont bien fonctionnéL le premier basé sur Sed était un "chouia" long (enfin tout est relatif, environ 15 seconde) et le second avec awk ultra rapide, quasi instantané.

Par contre nesthib, ne pas taper ;=)
j'ai lancé ton script plusieurs fois et ... rien
Aucun message d'erreur, pas de retour dans le terminal ?
Aurais-je oublié quelque chose !

En tout cas un grand merci car votre coup de main m'a sacrément dépanné.
smile

Hors ligne