[AWK] lire un deuxième fichier selon condition

Signaler
Messages postés
2
Date d'inscription
lundi 7 juin 2021
Statut
Membre
Dernière intervention
7 juin 2021
-
Messages postés
29880
Date d'inscription
jeudi 12 mai 2005
Statut
Modérateur
Dernière intervention
11 juin 2021
-
Bonjour,
Après avoir écumer les forums, je viens poser ma question:
J'ai 2 fichiers qui contiennent des données presque équivalentes:

1er Fichier: "tmp_paramTest"
[MESSAGE_A]
NOM_[0-9] , PARAMETRE....

2ème Fichier: "tmp_param.txt"
[MESSAGE_A]
NOM, ISSU REGROUPEMENT , PARAMETRE....

et je dois sortir un fichier (datas_brutes) qui prend :
MESSAGE_A, NOM,PARAMETRES, REGROUPEMENT
(je peux aussi avoir des cas: MESSAGE_A, NOM_0,PARAMETRES, )

Mon code est ci-dessous:
awk ' BEGIN { FS=","}
 {
  if ( $1 ~ /\[[A-Z].+/  )
  {
   tmp=$1
  }
  else if ( $1 ~ /^[A-Z].*_[0-9]./ )
  {
   regroup=$1
  }
  else if ( $4 ~ / pattern / )
  {
   print  $2" , "$1" , " tmp" , " $4" , " $5" , " $6" , " $7" , " $8" , " $9
  }
  
 }' "tmp_paramTest" var_param_file=tmp_param.txt > datas_brutes 


Pour le moment je recupère tout mais je n'arrive pas à lire le deuxième fichier tmp_param.txt (avec getline ou autres) dans ma condition de else If ( $1 ~ /^[A-Z].*_[0-9]./ ) pour transposer le NOM_[0-9] en NOM. (sachant que certains éléments de type NOM_[0-9] n'existeront pas dans le fichier à parser d'où la verification et pas juste NOM_[0-9] = NOM)

J'ai essayé les getline que je n'arrive pas à mettre en oeuvre correctement... (awk: 0602-576 A print or getline function must have a file name.voilà le type d'erreur que j'obtiens)

J'espère avoir été clair et que vous verrez une solution à mon problème (avec les explications qui vont bien!)
Bonne soirée

8 réponses

Messages postés
29880
Date d'inscription
jeudi 12 mai 2005
Statut
Modérateur
Dernière intervention
11 juin 2021
7 121
Bonjour,

Malheureusement ce n'est pas très clair.

Il faudrait nous partager deux fichiers d'entrée (quitte à les simplifier / anonymiser) pour qu'on puisse tester. L'idéal serait de nous dire qu'est ce que tu attends en sortie.

Dernière question, veux-tu le faire absolument en awk, ou est ce qu'une solution en python pourrait te convenir ?

Bonne chance
Messages postés
2
Date d'inscription
lundi 7 juin 2021
Statut
Membre
Dernière intervention
7 juin 2021

Bonjour mamiemando,

Je me doutais...

1er fichier :
[MESSAGE_A]
VARIABLE_0            = SPEED VALIDITY                    , , HEX ,               1,     ,  1, 15,  1, 0, 
VARIABLE_1            = DATA  LAT VALIDITY                    , , HEX ,               1,     ,  1, 14,  1, 0, 
VARIABLE_2            = DATA LONG VALIDITY                     , , HEX ,               1,     ,  1, 13,  1, 0, 
[MESSAGE_B]
VAR_0            = VALIDITY TEST                   , , HEX ,               1,     ,  1, 15,  1, 0, 
VAR_8         = DATA  VALIDITY                    , , HEX ,               1,     ,  1, 14,  1, 0, 


2ème fichier :
[MESSAGE_A]
VARIABLE            = REGROUPEMENT                    , , HEX ,               1,     ,  1, 15,  1, 0, 
[MESSAGE_B]
VAR_0            = VALIDITY TEST                   , , HEX ,               1,     ,  1, 15,  1, 0, 
VAR_8            = DATA  VALIDITY                    , , HEX ,               1,     ,  1, 14,  1, 0, 


Ce que j'attends en sortie:

MESSAGE_A,VARIABLE,REGROUPEMENT  , , HEX ,               1,     ,  1, 15,  1, 0, 
MESSAGE_B,VAR_0  ,  VALIDITY TEST                   , , HEX ,               1,     ,  1, 15,  1, 0, 
MESSAGE_B,VAR_8  ,  DATA  VALIDITY                    , , HEX ,               1,     ,  1, 14,  1, 0, 


Pour le python, je ne maîtrise pas du tout je n'ai pas le temps de me lancer dans du python (un jour peut-être).
Le
awk/shell/sed/tr
serait le mieux...
Mon problème est de faire matcher le 2ème fichier avec le premier pour ce type de données... Pour le reste j'y suis arrivée...

J'espère que cette fois c'est mieux ^^
Merci en tout cas pour ta réactivité
Messages postés
29880
Date d'inscription
jeudi 12 mai 2005
Statut
Modérateur
Dernière intervention
11 juin 2021
7 121
Bonjour,

Merci c'est déjà plus clair (mais pas encore complètement :p).

Il y a quelques trucs que je n'ai toujours pas compris.

1) À quoi sert le 1er fichier ? J'ai l'impression que pour obtenir ton fichier de sortie le 2ème fichier est suffisant (on garde le texte entre crochet, on l'ajoute en début de ligne, et on change le
=
par une
,
.

2) Aux espaces près, quelle est la différence entre le message B des deux fichiers d'entrée ?

3) Concernant le message A, pourquoi les lignes du 2ème fichier sont conservées, mais pas celles du premier ?

4) Est-ce que les espaces ont une importance (en particulier dans le fichier de sortie) ?

L'idéal serait peut-être d'expliquer, avec des mots, le comportement que devrait avoir le programme attendu. Ensuite concernant le langage, quoi que tu veuilles faire, ce sera plus simple à écrire en python, mais on peut essayer en shell dans un premier temps.

Bonne chance

Bonjour,
Pour faire simple, le fichier 1 décrit en détail les éléments du fichier 2 qui sont appelé données de regroupement.
Dans le premier, il faut que je récupère le détail de la deuxième colonne mais le nom de la première colonne du fichier 2.
Ce qui permet de dire que ce sont des données regroupées est dans le fichier 1 le _[0-9] et dans le fichier 2 le mot REGROUPEMENT de la deuxième colonne.
Mais attention certaines données du fichier 1 comporte le _[0-9] mais ne sont pas des données de regroupement...

1) Pour ce qui est du mot en [ ] j'ai déjà réussi à le faire (si tu prends le code au dessus tu verras ça sort correctement)

2) Rien et c'est la l'exception qu'il ne faut pas traiter si on l'a rencontre (bête recopie avec mise en forme)

3) en faite pour le message A, je veux les deux info :
MESSAGE_A,VARIABLE, SPEED VALIDITY ,REGROUPEMENT , HEX , 1, , 1, 15, 1, 0,
MESSAGE_A,VARIABLE, DATA LAT VALIDITY , REGROUPEMENT , HEX , 1, , 1, 14, 1, 0, *
MESSAGE_A,VARIABLE, DATA LONG VALIDITY ,REGROUPEMENT , HEX , 1, , 1, 13, 1, 0,

C'est plutot ça la sortie du message_A et là on comprend mieux le besoin du fichier 1 (désolée pour l'erreur j'ai été trop vite)

4) Pour la mise en forme je m'en accomoderai ce n'est pas le plus problématique pour moi. il faut par contre que les noms avec des espaces les gardes mais avant/après je m'en fiche mon fichier de sortie est un csv exploité à "la main"

Par avance merci ^^
Bonne journée
Messages postés
29880
Date d'inscription
jeudi 12 mai 2005
Statut
Modérateur
Dernière intervention
11 juin 2021
7 121
2) Rien et c'est la l'exception qu'il ne faut pas traiter si on l'a rencontre (bête recopie avec mise en forme)

Tu veux dire qu'on recopie les lignes du 2e fichiers vers celle du fichier de sortie ? Et je suppose qu'il en va de même pour fichier 1 ?

3) en fait pour le message A, je veux les deux info [...]

Déjà il y a trois lignes, et quid de la ligne
MESSAGE_A,VARIABLE,REGROUPEMENT  , , HEX ,               1,     ,  1, 15,  1, 0, 
? Faut-il la garder ? S'il faut la filtrer, pourquoi ? Parce qu'il y a le mot
REGROUPEMENT
?

4) Pour la mise en forme je m'en accomoderai ce n'est pas le plus problématique pour moi. il faut par contre que les noms avec des espaces les gardes mais avant/après je m'en fiche mon fichier de sortie est un csv exploité à "la main"

Ok, quoi qu'il faudrait que tu prennes ton temps pour expliquer clairement
  • ce que contient
    fichier1.txt
    ;
  • ce que contient
    fichier2.txt
    ;
  • ce que doit contenir
    fichier_sortie.txt
    ;


Voici ma compréhension actuelle de ton problème.
  • Tu as des fichiers (disons 2) d'entrée, décomposés en sections, dont le titre est marqué entre crochets.
  • Au sein de chaque section de ces fichiers d'entrées, tu as plusieurs lignes qui contiennent un nom de variable, un
    =
    , et une suite de valeurs séparées par des
    ,
    .
  • En sortie, tu veux générer un fichier csv, tel que :
    • chaque ligne correspond à (au moins) un des fichiers d'entrée ;
    • chaque ligne contient en première colonne le nom de la section correspondante ;
    • chaque ligne contient en deuxième colonne le nom de la section correspondant ;
    • les colonnes suivantes correspondent aux valeurs de la variable.
  • En cas de collision de clé (même nom de section et même nom de variable dans les deux fichiers) on ne conserve qu'un seul exemplaire, car les fichiers d'entrées sont supposés contenir les mêmes valeurs (dans ton exemple, voir la clé
    MESSAGE_B, VARIABLE_0
    par exemple).


Est-ce correct ?

Si oui, voici ce que ça donne en python (appelons le
script.py
) :

#!/usr/bin/env python3

import re
from collections import defaultdict
from pprint import pprint

RE_SECTION = re.compile("\[(.*)\]")

def process_file(filename, d):
    with open(filename) as f:
        for line in f.readlines():
            m = RE_SECTION.match(line)
            if m:
                section = m.group(1)
            elif "=" in line:
                tab = line.split("=")
                variable = tab[0].strip()
                values = [value.strip() for value in tab[1].split(",")]
                d[(section, variable)] = values

def export_csv(d):
    return "\n".join(
        ", ".join(
            value
            for value in [section, variable] + values
        )   
        for ((section, variable), values) in d.items()
    )

d = defaultdict(lambda: defaultdict(dict))
for filename in ["fichier1.txt", "fichier2.txt"]:
    process_file(filename, d)
print(export_csv(d))


... la commande pour l'exécuter :

python3 script.py fichier1.txt fichier2.txt


Avec
fichier1.txt
qui contient

[MESSAGE_A]
VARIABLE_0            = SPEED VALIDITY                    , , HEX ,               1,     ,  1, 15,  1, 0, 
VARIABLE_1            = DATA  LAT VALIDITY                    , , HEX ,               1,     ,  1, 14,  1, 0, 
VARIABLE_2            = DATA LONG VALIDITY                     , , HEX ,               1,     ,  1, 13,  1, 0, 
[MESSAGE_B]
VAR_0            = VALIDITY TEST                   , , HEX ,               1,     ,  1, 15,  1, 0, 
VAR_8         = DATA  VALIDITY                    , , HEX ,               1,     ,  1, 14,  1, 0,


... et
fichier2.txt
qui contient

[MESSAGE_A]
VARIABLE            = REGROUPEMENT                    , , HEX ,               1,     ,  1, 15,  1, 0, 
[MESSAGE_B]
VAR_0            = VALIDITY TEST                   , , HEX ,               1,     ,  1, 15,  1, 0, 
VAR_8            = DATA  VALIDITY                    , , HEX ,               1,     ,  1, 14,  1, 0,


... voici le résultat :

MESSAGE_A, VARIABLE_0, SPEED VALIDITY, , HEX, 1, , 1, 15, 1, 0, 
MESSAGE_A, VARIABLE_1, DATA LAT VALIDITY, , HEX, 1, , 1, 14, 1, 0,
MESSAGE_A, VARIABLE_2, DATA LONG VALIDITY, , HEX, 1, , 1, 13, 1, 0,
MESSAGE_B, VAR_0, VALIDITY TEST, , HEX, 1, , 1, 15, 1, 0,
MESSAGE_B, VAR_8, DATA VALIDITY, , HEX, 1, , 1, 14, 1, 0,
MESSAGE_A, VARIABLE, REGROUPEMENT, , HEX, 1, , 1, 15, 1, 0,


Est-ce que tu voulais obtenir ? (on peut facilement adapter
export_csv
si tu veux trier les lignes selon les deux premières colonnes).

Bonne chance

J'ai repris ton message que j'ai mis à jour avec mon besoin ^^
- Tu as des fichiers (disons 2) d'entrée, décomposés en sections, dont le titre est marqué entre crochets. -> oui
- Au sein de chaque section de ces fichiers d'entrées, tu as plusieurs lignes qui contiennent un nom de variable, un =, et une suite de valeurs séparées par des ,. -> oui
- En sortie, tu veux générer un fichier csv, tel que : -> oui
- chaque ligne correspond à (au moins) un des fichiers d'entrée ; -> non chaque ligne correspond au fichier 2 sauf s'il s'agit d'un regroupement alors on récupère le nom de la variable du fichier 2 et le détail du fichier 1 + on précise regroupement pour pas perdre l'info qui me sera utile pour un autre script (une variable regroupée du fichier 2 correspond à plusieurs lignes dans le fichier 1
- chaque ligne contient en première colonne le nom de la section correspondante ; -> oui
- chaque ligne contient en deuxième colonne le nom de la section correspondant ; -> tu voulais surement dire "VARIABLE correspondante"
- les colonnes suivantes correspondent aux valeurs de la variable. -> oui + la notion de REGROUPEMENT si c'est le cas
- En cas de collision de clé (même nom de section et même nom de variable dans les deux fichiers) on ne conserve qu'un seul exemplaire, car les fichiers d'entrées sont supposés contenir les mêmes valeurs (dans ton exemple, voir la clé MESSAGE_B, VARIABLE_0 par exemple). -> oui

petite précision (importante): je travaille sur serveur unix et python n'est pas natif donc le script python me semble compliqué :/ je n'ai pas les droits d'installation.
Messages postés
29880
Date d'inscription
jeudi 12 mai 2005
Statut
Modérateur
Dernière intervention
11 juin 2021
7 121
Bonjour

- chaque ligne correspond à (au moins) un des fichiers d'entrée ; -> non chaque ligne correspond au fichier 2 sauf s'il s'agit d'un regroupement alors on récupère le nom de la variable du fichier 2 et le détail du fichier 1 + on précise regroupement pour pas perdre l'info qui me sera utile pour un autre script (une variable regroupée du fichier 2 correspond à plusieurs lignes dans le fichier 1

Peux-tu donner un exemple ? En particulier, est-ce que le programme que je t'ai proposé renvoie ce qu'il fallait ?

- chaque ligne contient en deuxième colonne le nom de la section correspondant ; -> tu voulais surement dire "VARIABLE correspondante"

Oui, effectivement.

petite précision (importante): je travaille sur serveur unix et python n'est pas natif donc le script python me semble compliqué :/ je n'ai pas les droits d'installation.

L'interpréteur
python3
peut s'installer au même titre que l'interpréteur
awk
.

Aparté python : J'ai bien compris que tu cherches avant tout une solution en shell et/ou
awk
. Je propose pour le moment une solution en python car c'est un langage plus pratique et que je maîtrise mieux, donc le temps d'accorder nos violons, c'est plus pratique. Pour information,
python
s'installe facilement sous tout linux digne de ce nom (e.g.
sudo apt install python3 sous ubuntu
).

Une fois que le problème posé sera complètement clair, il sera toujours temps de le réécrire en
awk
ou en shell.

Bonne chance

Bonjour,
ok super! accordons nos violons ^^!

depuis ton exemple: on y est presque:*
Ce que j'ai souligné disparait (je n'ai pas trouvé comment barré ^^) et ce qui est en gras ajouté
MESSAGE_A, VARIABLE_0, SPEED VALIDITY, REGROUPEMENT , HEX, 1, , 1, 15, 1, 0,
MESSAGE_A, VARIABLE_1, DATA LAT VALIDITY, REGROUPEMENT , HEX, 1, , 1, 14, 1, 0,
MESSAGE_A, VARIABLE_2, DATA LONG VALIDITY, REGROUPEMENT , HEX, 1, , 1, 13, 1, 0,
MESSAGE_B, VAR_0, VALIDITY TEST, , HEX, 1, , 1, 15, 1, 0,
MESSAGE_B, VAR_8, DATA VALIDITY, , HEX, 1, , 1, 14, 1, 0,
MESSAGE_A, VARIABLE, REGROUPEMENT, , HEX, 1, , 1, 15, 1, 0,

En tout cas on y est presque et j'espère que tu as mieux compris ce que j'ai besoin !
Merci pour le temps que tu y passes !
Messages postés
29880
Date d'inscription
jeudi 12 mai 2005
Statut
Modérateur
Dernière intervention
11 juin 2021
7 121
Bonjour,

En tout cas on y est presque et j'espère que tu as mieux compris ce que j'ai besoin !

On s'en approche, mais tu reste toujours un peu vague :-)

Dans ton exemple :
  • Pourquoi le mot clé REGROUPEMENT est inséré en 4e colonne (pourquoi la 4e et pas une autre) ? Est-ce le rôle spécifique de cette colonne ? Est-ce que c'est parce que c'est la première colonne disponible ?
  • Dans ton exemple REGROUPEMENT était le 3e élément de la ligne supprimée, mais le 4e des lignes corrigées. Est-ce normal ?
  • Pourquoi est-ce que la ligne qui contient le mot REGROUPEMENT est supprimée ? Est-ce dû à la présence du mot REGROUPEMENT ou à une autre raison ?
  • Est-ce que dans le fichier de sortie, les colonnes ont un rôle particulier (e.g. la colonne 4 contient REGROUPEMENT ou rien) ?


Dit autrement, quelles sont les règles, sous leur générique, qui répondent à ces questions ?