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 03/07/2020, à 23:53

wambi

Concaténer deux lignes consécutives d'un fichier csv avec awk

Bonjour,
Débutant en shell , je demande votre aide car j'ai du mal a m'en sortir avec la commande awk.
J'aimerai créer un fichier csv nommé "fichier2.csv"  à partir d'un fichier source "fifier1.csv" qui est de la forme:

,,be,be,be,ca,ca,ca
Prospect_date,UID,flag Status,Sub_date,Report_date,flag Status,Sub_date,Report_date
2020-02-20,QC-001,ACC,2020-02-21,2020-02-21,,,
2020-02-20,TC-011,,,,ACC,2020-02-21,2020-02-21

1- La ligne 1 du fichier contient les pays mais avec des champs qui sont vides
2- La ligne est l'entête à concaténer avec la ligne 1 telle que:

Prospect_date,UID,flag Status_be,Sub_date_be,Report_date_be,flag Status_ca,Sub_date_ca,Report_date_ca
2020-02-20,QC-001,ACC,2020-02-21,2020-02-21,,,
2020-02-20,TC-011,,,,ACC,2020-02-21,2020-02-21

3- Ensuite je ne dois garder que les champs "flag status" de sorte que le fichier devient:

enr date, UID, flag Status_be, flag Status_ca
2020-02-20 ,QC-001, ACC - be,
2020-02-20,TC-011,,ACC - ca
2019-02-20,QC-001,ACC - be,

4- Le fichier final sera:
enr date, UID, flag Status,Pays
2020-02-20 ,QC-001, ACC - be,be
2020-02-20,TC-011,ACC - ca,ca
2019-02-20,QC-001,ACC - be,ca

Quelqu'un peut-il m'aider svp?

Merci.

Dernière modification par wambi (Le 03/07/2020, à 23:53)

Hors ligne

#2 Le 04/07/2020, à 00:35

Vobul

Re : Concaténer deux lignes consécutives d'un fichier csv avec awk

Question : est-ce que tu es obligé d'utiliser awk ? Non parce que bon y'a des trucs bien plus sympas qui existent quand même :

sudo apt-get install python3-pip
pip install --user pandas
python
>>> import pandas as pd
>>> df = pd.read_csv('fichier1.csv')
>>> df.head()

Voilà ça c'est le début, après tu recherches tout ce que tu souhaites faire avec le mot-clé "pandas" et zou ! Tu verras il y a PLEIN de tutoriels pour pandas et c'est vraiment un truc qui vaut la peine de savoir utiliser. Par exemple si tu veux plotter un truc tu peux le faire direct depuis pandas, c'est bien pratique wink


Vobul
Utilisez le retour utilisable de commandes !!!
J'aime la langue française, mais je parle franglais, deal with it.
RTFM

Hors ligne

#3 Le 04/07/2020, à 00:49

Watael

Re : Concaténer deux lignes consécutives d'un fichier csv avec awk

salut,

ce n'est pas exactement une concaténation, qui consiste à ajouter du contenu à la suite d'une chaîne).
là, il faut , en effet, concaténer, mais concaténer les champs de la deuxième ligne avec le contenu des champs de la première ligne.
"il suffit" de mémoriser les champs de la première ligne dans un tableau indexé, et d'ajouter ce contenu au champs correspondants de la deuxième ligne.
mais déjà, on peut ne conserver que les deux premiers champs, et ceux qui "matchent" l'expression recherchée,
par la suite, on se servira de ces indices pour afficher uniquement les champs dont le numéro correspond à ces indices.

à l'étape 3, il y a des données qui apparaissent, dont je ne vois pas l'origine.


Connected \o/
Welcome to sHell. · eval is evil.

Hors ligne

#4 Le 04/07/2020, à 07:17

wambi

Re : Concaténer deux lignes consécutives d'un fichier csv avec awk

Bonjour,

Tout d'abord merci pour vos réponses. Pour répondre à Vobul, malheureusement, awk est imposé.

L'explication de Watael est exact:
"...mais concaténer les champs de la deuxième ligne avec le contenu des champs de la première ligne"

Les champ à conserver doivent matcher avec l'expression "flag Status".

A l'étape 3, pour chaque pays, il y'a une concaténation avec le "flag Staus" en rajoutant le pays pour identifier le falg.
Exemple: Si Pays = be alors flag Status= ACC - be
                Si Pays = ca alors flag Status = ACC - ca

Merci pour votre aide.

Hors ligne

#5 Le 04/07/2020, à 12:59

kamaris

Re : Concaténer deux lignes consécutives d'un fichier csv avec awk

Je suppose que le passage de Prospect_date à enr date entre les points 2 et 3 du premier post est une faute de copier-coller ?
Sinon, il faudrait rajouter une petite substitution à la commande ci-dessous :

awk 'BEGIN{OFS=FS=","; PROCINFO["sorted_in"]="@ind_num_asc"} NR==1{for (i=1;i<=NF;i++) if ($i){s=i; break} for (i=s;i<=NF;i++) if ($i && ! a[$i]) a[$i]=i} NR==2{n=-1; for (c in a) $(++n+s)=$(a[c])"_"c; NF=s+n; print} NR>2{n=-1; for (c in a) if ($(a[c])) $(++n+s)=$(a[c])" - "c; else $(++n+s)=""; NF=s+n; print}' fichier1.csv >fichier2.csv

Ou, sous une forme un peu développée :

awk '
  BEGIN{OFS=FS=","; PROCINFO["sorted_in"]="@ind_num_asc"}
  NR==1{for (i=1;i<=NF;i++) if ($i){s=i; break} for (i=s;i<=NF;i++) if ($i && ! a[$i]) a[$i]=i}
  NR==2{n=-1; for (c in a) $(++n+s)=$(a[c])"_"c; NF=s+n; print}
  NR>2{n=-1; for (c in a) if ($(a[c])) $(++n+s)=$(a[c])" - "c; else $(++n+s)=""; NF=s+n; print}
' fichier1.csv >fichier2.csv

Dernière modification par kamaris (Le 04/07/2020, à 13:03)

Hors ligne

#6 Le 04/07/2020, à 16:36

Watael

Re : Concaténer deux lignes consécutives d'un fichier csv avec awk

notez que les fonctions de tri (PROCINFO["sorted_in"], asort, asorti) n'existent que sur GNU/awk.
ça vaudrait peut-être la peine de préciser gawk quand on utilise des "GNUismes".


Connected \o/
Welcome to sHell. · eval is evil.

Hors ligne

#7 Le 04/07/2020, à 16:45

kamaris

Re : Concaténer deux lignes consécutives d'un fichier csv avec awk

Argh ! Oui, tu as raison, d'habitude je le précise.
Là je ne me suis basé que sur le retour de l'option --lint, et je me suis fait avoir hmm.

---

On peut se passer assez facilement du tri à l'aide d'un autre tableau :

awk 'BEGIN{OFS=FS=","} NR==1{for (i=1;i<=NF;i++) if ($i){s=i; break} for (i=s;i<=NF;i++) if ($i && ! a[$i]) {a[$i]=i; b[i]=$i}} NR==2{n=-1; for (i in b) $(++n+s)=$i"_"b[i]; NF=s+n; print} NR>2{n=-1; for (i in b) if ($i) $(++n+s)=$i" - "b[i]; else $(++n+s)=""; NF=s+n; print}' fichier1.csv >fichier2.csv

ou, forme développée :

awk '
  BEGIN{OFS=FS=","}
  NR==1{for (i=1;i<=NF;i++) if ($i){s=i; break} for (i=s;i<=NF;i++) if ($i && ! a[$i]) {a[$i]=i; b[i]=$i}}
  NR==2{n=-1; for (i in b) $(++n+s)=$i"_"b[i]; NF=s+n; print}
  NR>2{n=-1; for (i in b) if ($i) $(++n+s)=$i" - "b[i]; else $(++n+s)=""; NF=s+n; print}
' fichier1.csv >fichier2.csv

Dernière modification par kamaris (Le 04/07/2020, à 17:07)

Hors ligne

#8 Le 04/07/2020, à 18:04

wambi

Re : Concaténer deux lignes consécutives d'un fichier csv avec awk

Bonjour Kamaris,

Merci pour ton aide. C'est génial!

Je viens de tester les deux codes et le résultat est conforme à ce qui est attendu à l'étape 3.

J'ai même rajouté un champ date (Enreg date) au début et 2 pays supplémentaires, cela a bien fonctionné en sortie.

Le résultat du script avec le séparateur de sortie "|" donne:

Prospect_date |UID        |flag Statut_be  |flag Status_ca |flag Status_fr |flag Status_ch
2020-02-20      |QC-001  |ACC - be         |                        |                      |
2020-02-20      |TC-011   |                        |ACC - ca         |                      |
2019-02-19      |QM-010  |                       |                        |ACC - fr         |
2019-02-15      |AC-002   |                       |                        |                      |ACC - ch

--> A la dernière étape (Etape 4), le fichier  doit avoir la forme:

Prospect_date |UID        |flag Statut  |Pays
2020-02-20      |QC-001  |ACC - be   | be     
2020-02-20      |TC-011   |ACC - ca   | ca         
2019-02-19      |QM-010  | ACC - fr   | fr   
2019-02-15      |AC-002   | ACC - ch |  ch 

Encore un fois grand merci de votre aide.

Hors ligne

#9 Le 04/07/2020, à 18:39

kamaris

Re : Concaténer deux lignes consécutives d'un fichier csv avec awk

Ah ok, j'avais pas bien compris pour l'étape 4.
Du coup, si l'étape 3 (ni aucune autre qui précède) n'a besoin d'être affichée, c'est plus simple : on peut tout faire en un coup, avec le premier code, et en ayant plus besoin de préciser d'ordre de tri pour le tableau (donc c'est bien du awk, même si pas forcément très portable…) :

awk 'BEGIN{OFS=FS=","} NR==1{for (i=1;i<=NF;i++) if ($i){s=i; break} for (i=s;i<=NF;i++) if ($i && ! a[$i]) a[$i]=i} NR==2{NF=s+1; $NF="Country"; print} NR>2{for (c in a) if ($(a[c])) {$s=$(a[c])" - "c; NF=s+1; $NF=c; break} print}' fichier1.csv >fichier2.csv

Forme développée :

awk '
  BEGIN{OFS=FS=","}
  NR==1{for (i=1;i<=NF;i++) if ($i){s=i; break} for (i=s;i<=NF;i++) if ($i && ! a[$i]) a[$i]=i}
  NR==2{NF=s+1; $NF="Country"; print}
  NR>2{for (c in a) if ($(a[c])) {$s=$(a[c])" - "c; NF=s+1; $NF=c; break} print}
' fichier1.csv >fichier2.csv

Évidemment, il faut que le fichier d'entrée ait le format auquel on s'attend, car il n'y aucune vérification à ce sujet dans ce code…

Hors ligne

#10 Le 05/07/2020, à 04:45

Watael

Re : Concaténer deux lignes consécutives d'un fichier csv avec awk

on peut regretter de ne pas avoir plus de lignes du fichier à traiter, avec la sortie attendue.


Connected \o/
Welcome to sHell. · eval is evil.

Hors ligne

#11 Le 05/07/2020, à 09:53

wambi

Re : Concaténer deux lignes consécutives d'un fichier csv avec awk

Bonjour Kamaris,

Désolé pour hier soir, je n'étais pas connecté.

Sinon, la dernière version marche avec le fichier avec 3 colonnes par pays.
Or dans un des fichiers, j'ai 9 champs par pays au début du traitement et le script ne marche plus.
Est-ce qu'on peut mettre une condition entre l'étape 2 et 3 pour dire:
Tant que pays, garder "flag Status"? . Cela permettra d'éviter au cas où le nombre de colonnes change.

Pour répondre à Watael, j'ai un fichier avec 9 colonnes pour chaque pays tels que:
"flag Status,Tech,Sub  date,Report date,Tech date,Contact date,Tech submit date,task date,Reg date"

Mais je ne peux le copier coller ici(C'est mal disposé, ça déborde sur l'écran et c'est pas digeste).

Saviez-vous comment on peut  joindre un fichier sur le forum?

Merci beaucoup.

Dernière modification par wambi (Le 05/07/2020, à 09:58)

Hors ligne

#12 Le 05/07/2020, à 14:51

wambi

Re : Concaténer deux lignes consécutives d'un fichier csv avec awk

Bonjour Kamaris,

Voici un exemple du fichier final avec 9 champs par pays.
C'est un peu long à l'écran mais je n'ai pas d'autre options sur le forum pour joindre le fichier.

--> Exemple du fichier

,,,be,be,be,be,be,be,be,be,be,ca,ca,ca,ca,ca,ca,ca,ca,ca              
Enreg_date,Prospect_date,UID,flag Status,Sub_date,Report_date,Sub_date,tech1_date,tech3_date,tech4_date,tech5_date,tech6_date,flag Status,Sub_date,Report_date,Sub_date,tech1_date,tech3_date,tech4_date,tech5_date,tech6_date
2020-02-20,2020-02-20,A001,ACC,2019-02-20,2019-02-21,2019-02-21,2019-02-21,2019-02-21,2019-02-21,2019-02-21,2019-02-21,ACC,2020-02-21,2020-02-21,2020-02-21,2020-02-21,2020-02-21,2020-02-21,2020-02-21,2020-02-21            
2020-02-20,2020-02-20,A002,ACC,2019-02-21,22019-02-21,2019-02-21,2019-02-21,2019-02-21,2019-02-21,22019-02-21,2019-02-21,v,v,v,v,v,v,v,v,v							                                                          
2019-03-19,2019-02-19,A003,ACC,2019-02-26,2019-02-26,2019-02-26,2019-02-26,2019-02-26,2019-02-26,2019-02-26,2019-02-26,ACC,2020-02-21,2020-02-21,2020-02-21,2020-02-21,2020-02-21,2020-02-21,2020-02-21,2020-02-21            
2019-03-19,2019-02-15,A004,v,v,,,v,v,v,v,v,ACC,2020-02-21,2020-02-21,2020-02-21,2020-02-21,2020-02-21,2020-02-21,2020-02-21,2020-02-21

- A l'étape 2 - 3, on obtient un fichier de ce format:

Enreg_date ,Prospect_date ,UID   ,flag Status_be ,flag Status_ca
2020-02-20  ,2020-02-20     ,A001 ,ACC - be         ,ACC - ca
2020-02-20  ,2020-02-20     ,A002 ,ACC - be         ,v - ca
2019-03-19  ,2019-02-19     ,A003 ,ACC - be         ,ACC - ca
2019-03-19  ,2019-02-15     ,A004 ,v - be               ,ACC - ca

- A l'étape 4, le fichier final devient:

Enreg_date ,Prospect_date ,UID   ,flag Status , Country
2019-03-19 ,2019-02-19      ,A003 , ACC - be  , be   
2019-03-19 ,2019-02-15      ,A004 , v - be      , be
2019-03-19 ,2019-02-19      ,A003 , ACC - ca  , ca
2019-03-19 ,2019-02-15      ,A004 , ACC - ca  ,ca
2020-02-20 ,2020-02-20      ,A001 , ACC - be  ,be
2020-02-20 ,2020-02-20      ,A002 , ACC - be  ,be   
2020-02-20 ,2020-02-20      ,A001 , ACC - ca  ,be   
2020-02-20 ,2020-02-20      ,A002 , v - ca        ,ca   

J'espère que cela répond à la demande de Watael.

Merci.

Dernière modification par wambi (Le 05/07/2020, à 14:57)

Hors ligne

#13 Le 05/07/2020, à 14:53

xubu1957

Re : Concaténer deux lignes consécutives d'un fichier csv avec awk

Bonjour,

Pour ajouter toi-même les balises code à tes précédents messages :

  • Cliquer sur  le lien « Modifier » en bas à droite du message

  • Sélectionner le texte

  • Cliquer sur le <> de l'éditeur de message

1578079461.png

comme indiqué dans le premier message du tutoriel Retour utilisable de commande

Voir règles du forum > balises BB code

Balise CODE :

C'est la balise à utiliser pour donner de longs messages d'erreurs, des contenus de fichiers de configuration, des commandes à taper, etc … Elle permet des messages plus "compacts", et est moins ambiguë que d'autres polices sur certains caractères.


Conseils pour les nouveaux demandeurs et pas qu'eux
Important : Pensez à passer vos sujets en [Résolu] lorsque ceux-ci le sont, au début du titre en cliquant sur Modifier sous le premier message, et un bref récapitulatif de la solution à la fin de celui-ci. Merci.                   Membre de Linux-Azur

Hors ligne

#14 Le 05/07/2020, à 15:57

Watael

Re : Concaténer deux lignes consécutives d'un fichier csv avec awk

moi aussi, je suis une grosse feignasse.
dis-nous, wambi, où en es-tu de la résolution de TON exercice, et de la rédaction de TON script ?

as-tu commencé à rédiger un algorithme en pseudo-code, plutôt que d'en faire un story-board ?

et par curiosité :
comment se fait-il que tu te trouves chargé d'une telle tâche, alors que tu ne connais pas le B-A-BA de awk ?


Connected \o/
Welcome to sHell. · eval is evil.

Hors ligne

#15 Le 05/07/2020, à 19:39

kamaris

Re : Concaténer deux lignes consécutives d'un fichier csv avec awk

wambi a écrit :

Sinon, la dernière version marche avec le fichier avec 3 colonnes par pays.
Or dans un des fichiers, j'ai 9 champs par pays au début du traitement et le script ne marche plus.

Le problème ne vient pas du nombre de champs par pays, ni du nombre de pays, mais du format des lignes qui suivent, qui n'est plus le même que précédemment.
En fait, tu as carrément fait évoluer le passage de l'étape 3 à l'étape 4, ou en tout cas apporté un complément qui ne pouvait pas être deviné plus haut.
Par ailleurs, ta première ligne des pays ne comporte pas deux pays, mais trois :

<be>
<ca>
<ca              >

Il faut enlever les espaces en fin de ligne.
Si tu enlèves ces espaces, les codes donnés en #5 et #7 pour l'étape 3 fonctionnent.
À partir de là, à toi de passer à l'étape 4 tongue

Hors ligne

#16 Le 05/07/2020, à 22:09

wambi

Re : Concaténer deux lignes consécutives d'un fichier csv avec awk

Bonsoir,

Ok, c'est noté et merci Kamaris.
Je vais vérifier le fichier et m'exercerais sur la partie 4 pour terminer.

Pour infos Watael, je travaille sur du SAP HANA avec un moteur d'intégration de données(en batch) et un langage particulier qui va avec.
Dernièrement, il y'a eu une migration d'applis sur du cloud Amazon EC2 et les applis ne fonctionnent plus correctement, d'où le passage sur du awk.
La personne qui devrait s'en occuper est partie et j'ai hérité de la suite.
Je crois que j'ai pris le soin d'indiquer au début que je n'avais aucune connaissance de awk...
Rassure toi, si je ne connaissais pas l'algo, je l'aurais pas décrit ni su quoi faire.

Encore une fois de plus, merci Kamaris, ça m'a vachement avancé.

Dernière modification par wambi (Le 05/07/2020, à 22:10)

Hors ligne

#17 Le 05/07/2020, à 22:16

Watael

Re : Concaténer deux lignes consécutives d'un fichier csv avec awk

je ne vais pas perdre plus de temps à commenter.


Connected \o/
Welcome to sHell. · eval is evil.

Hors ligne

#18 Le 12/07/2020, à 16:03

LeoMajor

Re : Concaténer deux lignes consécutives d'un fichier csv avec awk

@watael
<Modéré>

Dernière modification par Ayral (Le 12/07/2020, à 18:09)

Hors ligne