IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Shell et commandes GNU Discussion :

Suppression des doublons dans chaque ligne d'un fichier


Sujet :

Shell et commandes GNU

  1. #21
    Membre chevronné
    Homme Profil pro
    Urbaniste
    Inscrit en
    Août 2023
    Messages
    387
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : Urbaniste

    Informations forums :
    Inscription : Août 2023
    Messages : 387
    Par défaut
    Citation Envoyé par disedorgue Voir le message
    Je suis de bonne humeur, voici donc quelques détails sur le awk:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    BEGIN{
            PROCINFO["sorted_in"]="@val_num_asc" #pour parcourir les tableaux assoc en triant sur les valeur par ordre croissant
    }
    {
            for (i=1;i<NF;i=i+2){ # on parcourt tous les champs impair
                    if (!B[$(i)]) { # si le champs n'existe pas encore dans le tableau
                            B[$(i)]=i # on crée la clé en lui associant en valeur le numero du champs (pour le tri)
                    }
                    A[$(i)][$(i+1)]=i # on crée un tableau bidimensionnel champs/valeur=numéro du champs (pour le tri) en meme temps un tableau associatif de clé permet de virer les doublons
            }
            for (i in B){ # on parcourt le te tbleau B trier par valeur (qui ici est le numéro du champs)
                    C=1
                    for(j in A[i]){ # on parcourt le tableau A via les clé du tableau B 
                            if (C==1){
                                    D[i]=j;C++
                            } 
                            else    
                                    D[i]=D[i]j
                            D[i]=gensub(/""([^"]*)"/,":[\\1]\"","g",D[i]) # on réecrit les valeurs des clé multiple
                    }
                    printf i"="D[i]" "
            }
            delete A
            print ""
    }
    Bonjour,

    pour ajouter à vos explications,
    https://www.gnu.org/software/gawk/manual/html_node/Controlling-Scanning.html
    https://www.shellunix.com/awk.html (pour les variables prédéfinies, NF)

    Et au cas où, la remarque de N_Bah était encore justifiée dans la dernière version corrigée,
    c'est sûrement un petit pépin.

    jour="5" article="pomme de terre" pepins="sans" categorie="légume" article="orange" pepins="avec" categorie="fruit"
    Ici ça donne,
    awk -F'[ =]' 'BEGIN{PROCINFO["sorted_in"]="@val_num_asc"}{for (i=1;i<NF;i=i+2){if (!B[$(i)]) {B[$(i)]=i};A[$(i)][$(i+1)]=i};for (i in B){C=1;for(j in A[i]){if (C==1){D[i]=j;C++} else D[i]=D[i]j;D[i]=gensub(/""([^"]*)"/,":[\\1]\"","g",D[i])}printf i"="D[i]" "}delete A;print ""}' bobawk.txt
    jour="3" article="banane" pepins="sans" categorie="fruit"
    jour="6" article="orange:[courgette]" pepins="avec:[sans]" categorie="fruit:[legume]"
    jour="5" article="pomme\" awk: ligne de commande:1: (FILENAME=bobawk.txt FNR=3) fatal*: tentative d'utiliser un scalaire comme tableau

    Bonne journée.

  2. #22
    Expert confirmé Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 429
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur intégration
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2012
    Messages : 4 429
    Par défaut
    mouais...
    Comme déjà précisé, quand on fait de l'exotique, on adapte à son besoin (y aura toujours une brêche)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    awk 'BEGIN{FPAT="[^ =]\"?[^=\"]*\"?";PROCINFO["sorted_in"]="@val_num_asc"}{for (i=1;i<NF;i=i+2){if (!B[$(i)]) {B[$(i)]=i};A[$(i)][$(i+1)]=i};for (i in B){C=1;for(j in A[i]){if (C==1){D[i]=j;C++} else D[i]=D[i]j;D[i]=gensub(/""([^"]*)"/,":[\\1]\"","g",D[i])}printf i"="D[i]" "}delete A;print ""}'

  3. #23
    Membre éclairé
    Homme Profil pro
    sans
    Inscrit en
    Juillet 2019
    Messages
    141
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : sans

    Informations forums :
    Inscription : Juillet 2019
    Messages : 141
    Par défaut
    Citation Envoyé par disedorgue Voir le message
    Qui ce lance pour un "PUR" bash (que de la builtin) ?
    j'ai honte j'arrive pas à le rentrer dans mon code

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    # mettons que j'ai une fonction comme suit
    merge_variables (){
     [ -f "$index" ] && {
       # $index est connu, c'est sûr, il existe, il est plein
       # ... et là le code qui va bien, mais comment je place $index dans ce bout de code ? :oops:
       # si on prend la dernière version de disedorgue ?
     
     }
     
    }
    Après le code ci-dessous fonctionne impeccablement si on considère que l'exécutable se trouve dans le même répertoire que $index (ou datas.txt ici)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    #!/usr/bin/gawk -f
     
    BEGIN{
        FS="[ =]"
        PROCINFO["sorted_in"]="@val_num_asc"
        ARGV[ARGC++]="datas.txt" #il est préférable d'indiquer le chemin absolu vers le fichier, et il faut adapter le nom du fichier !
    }
    #suit le reste du script inchangé
    {
    	for (i=1;i<NF;i=i+2){
    		if (!B[$(i)]) { B[$(i)]=i } ;A[$(i)][$(i+1)]=i }
    		for (i in B){
    			C=1 ; for(j in A[i]){ if (C==1){ D[i]=j;C++ } else D[i]=D[i]j ; D[i]=gensub(/""([^"]*)"/,":[\\1]\"","g",D[i])
    		}
    		printf i"="D[i]" "
    	}
    	delete A
    	print ""
    }

  4. #24
    Expert confirmé Avatar de papajoker
    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2013
    Messages
    2 334
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nièvre (Bourgogne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2013
    Messages : 2 334
    Par défaut
    bonjour

    si nous avons du gawk, bash et php, pourquoi pas du python ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    #!/usr/bin/env python
    import sys
    from collections import defaultdict
    from pathlib import Path
     
    fichier = "./truc.datas"
    if len(sys.argv) > 1:
        fichier = sys.argv[1]
    else:
        datas = """
        jour="3" article="banane" pepins="sans" categorie="fruit" article="banane" pepins="sans" categorie="fruit"
        jour="5" article="pomme de terre" pepins="sans" categorie="légume" article="orange" pepins="avec" categorie="fruit"
        jour="55" article="pomme de terre" pepins="sans" categorie="légume" article="orange" pepins="sans" categorie="fruit"
        jour="6" article="orange" pepins="avec" categorie="fruit" article="courgette" pepins="sans" categorie="légume"
        jour="7" article="orange" pepins="avec" categorie="fruit" article="banane" pepins="sans" categorie="fruit"
        """
        Path(fichier).write_text(datas)
     
    jours = {}
    with open(fichier) as f:
        for ligne in f:
            ligne = ligne.strip()
            if not ligne:
                continue
            for entree in ligne.split('" '):
                k, v = entree.split("=", maxsplit=2)[0:2]
                v = v.replace('"', '')
                if k == "jour":
                    jour = v
                    jours[jour] = defaultdict(list)
                else:
                    jours[jour][k].append(v)
     
    # A revoir si 3 elements dans la journée : pepins="sans,sans,avec" ?
    for _, jour in jours.items():   # virer les doublons
        for key, keys in jour.items():
            jour[key] = list(set(jour[key]))
     
    for j, jour in jours.items():
        print(f'{j:>2}-> ', end="")
        for key, values in jour.items():
            sub = f':{":".join("["+v+"]" for v in values[1:])}'
            print(f'{key}="{values[0]}{sub if len(sub) > 1 else ""}"', end=" ")
        print()
     
    if fichier == "./truc.datas":
        Path(fichier).unlink()

  5. #25
    Membre chevronné
    Homme Profil pro
    Urbaniste
    Inscrit en
    Août 2023
    Messages
    387
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : Urbaniste

    Informations forums :
    Inscription : Août 2023
    Messages : 387
    Par défaut
    Citation Envoyé par papajoker Voir le message
    bonjour

    si nous avons du gawk, bash et php, pourquoi pas du python ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    #!/usr/bin/env python
    import sys
    from collections import defaultdict
    from pathlib import Path
     
    fichier = "./truc.datas"
    if len(sys.argv) > 1:
        fichier = sys.argv[1]
    else:
        datas = """
        jour="3" article="banane" pepins="sans" categorie="fruit" article="banane" pepins="sans" categorie="fruit"
        jour="5" article="pomme de terre" pepins="sans" categorie="légume" article="orange" pepins="avec" categorie="fruit"
        jour="55" article="pomme de terre" pepins="sans" categorie="légume" article="orange" pepins="sans" categorie="fruit"
        jour="6" article="orange" pepins="avec" categorie="fruit" article="courgette" pepins="sans" categorie="légume"
        jour="7" article="orange" pepins="avec" categorie="fruit" article="banane" pepins="sans" categorie="fruit"
        """
        Path(fichier).write_text(datas)
     
    jours = {}
    with open(fichier) as f:
        for ligne in f:
            ligne = ligne.strip()
            if not ligne:
                continue
            for entree in ligne.split('" '):
                k, v = entree.split("=", maxsplit=2)[0:2]
                v = v.replace('"', '')
                if k == "jour":
                    jour = v
                    jours[jour] = defaultdict(list)
                else:
                    jours[jour][k].append(v)
     
    # A revoir si 3 elements dans la journée : pepins="sans,sans,avec" ?
    for _, jour in jours.items():   # virer les doublons
        for key, keys in jour.items():
            jour[key] = list(set(jour[key]))
     
    for j, jour in jours.items():
        print(f'{j:>2}-> ', end="")
        for key, values in jour.items():
            sub = f':{":".join("["+v+"]" for v in values[1:])}'
            print(f'{key}="{values[0]}{sub if len(sub) > 1 else ""}"', end=" ")
        print()
     
    if fichier == "./truc.datas":
        Path(fichier).unlink()
    Bonjour,

    on finira peut être par voir poindre une version brainfuck.

    J'en rajoute une couche, pourquoi pas ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
     
    package main
     
    import (
    	"bufio"
    	"fmt"
    	"os"
    	"sort"
    	"strings"
    )
     
    func main() {
     
    	text := `jour="3" article="banane" pepins="sans" categorie="fruit" article="banane" pepins="sans" categorie="fruit"
    jour="5" article="pomme de terre" pepins="sans" categorie="légume" article="orange" pepins="avec" categorie="fruit"
    jour="55" article="pomme de terre" pepins="sans" categorie="légume" article="orange" pepins="sans" categorie="fruit"
    jour="6" article="orange" pepins="avec" categorie="fruit" article="courgette" pepins="sans" categorie="légume"
    jour="7" article="orange" pepins="avec" categorie="fruit" article="banane" pepins="sans" categorie="fruit"
    `
    	r := strings.NewReader(text)
     
    	sc := bufio.NewScanner(r)
     
    	type kv struct {
    		name  string
    		value string
    	}
     
    	for sc.Scan() {
     
    		var n []kv
    		key := ""
    		value := ""
    		in_quote := false
    		in_escape := false
    		in_key := true
     
    		for _, r := range sc.Text() {
    			if !in_quote && r == '"' {
    				in_quote = true
    				continue
    			}
    			if in_quote && r == '\\' {
    				in_escape = true
    				continue
    			}
    			if in_quote && r == '"' {
    				if in_escape {
    					in_escape = false
    				} else {
    					in_quote = false
    					continue
    				}
    			}
     
    			if !in_quote && r == ' ' {
    				if key != "" {
    					n = append(n, kv{name: key, value: value})
    				}
    				key = ""
    				value = ""
    				in_key = true
    				continue
    			}
    			if in_key && r == '=' {
    				in_key = false
    				continue
    			}
    			if in_key {
    				key += string(r)
    			} else {
    				value += string(r)
    			}
    		}
     
    		if key != "" {
    			n = append(n, kv{name: key, value: value})
    		}
     
    		articles := map[string]map[string]string{}
    		keys := map[string]int{}
     
    		var article string
    		var jour string
    		var t int
    		for _, a := range n {
    			if a.name == "jour" {
    				jour = a.value
    				continue
    			}
    			if a.name == "article" {
    				article = a.value
    			}
    			keys[a.name] = t
    			t++
    			if _, ok := articles[article]; !ok {
    				articles[article] = map[string]string{}
    			}
    			articles[article][a.name] = a.value
    		}
     
    		var ukeys []string
    		for k := range keys {
    			ukeys = append(ukeys, k)
    		}
    		sort.Slice(ukeys, func(i, j int) bool {
    			return keys[ukeys[i]] < keys[ukeys[j]]
    		})
     
    		var res string
    		res = fmt.Sprintf("jour=%q", jour)
    		for _, key := range ukeys {
    			var val string
    			var prev string
    			var j int
    			for _, k := range articles {
    				if j < 1 {
    					val += k[key]
    				} else if prev != k[key] {
    					val += fmt.Sprintf(":[%v]", k[key])
    				}
    				prev = k[key]
    				j++
    			}
    			res += fmt.Sprintf(" %v=%q", key, val)
    		}
    		res = strings.TrimSpace(res)
    		fmt.Fprintf(os.Stdout, "%v\n", res)
    	}
    }
    Bonne journée.

  6. #26
    Membre éclairé
    Homme Profil pro
    sans
    Inscrit en
    Juillet 2019
    Messages
    141
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : sans

    Informations forums :
    Inscription : Juillet 2019
    Messages : 141
    Par défaut
    Citation Envoyé par unanonyme Voir le message
    on finira peut être par voir poindre une version brainfuck.
    C'est quoi une brainfuck ?

    Coucou
    Finalement j'ai fait autrement, notamment une fonction qui traite ligne par ligne chaque champ en le numérotant (numéro de place, ordre fixe voulu), en fonction de la clé qu'il est(non de son ordre dans la ligne ; exemple toute occurrence d' article -> 1article) puis tr pour mettre chaque champ à la ligne puis sort -u, on retire les num et on replace sur la ligne.
    Reste à gérer les autres , les vrais doublons article=pommes et article=orange par exemple, autre fonction qui recompose la ligne en concaténant et mettant en forme article= puis en remplaçant line par new_line , bon faut une boucle.
    Quand je regarde ma ligne de sed je me dis qu'il me faut un écran plus large (c'est tellement esthétique qu'on va pas "baliser", mais ça marche )

  7. #27
    Membre chevronné
    Homme Profil pro
    Urbaniste
    Inscrit en
    Août 2023
    Messages
    387
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : Urbaniste

    Informations forums :
    Inscription : Août 2023
    Messages : 387

  8. #28
    Membre éclairé
    Homme Profil pro
    sans
    Inscrit en
    Juillet 2019
    Messages
    141
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : sans

    Informations forums :
    Inscription : Juillet 2019
    Messages : 141
    Par défaut

    Comme son nom ne le suggère pas pour un anglophobe, les programmes Brainfuck sont difficiles à comprendre, peut-être même dangereux pour la santé mentale des programmeurs.
    ... je vois ...

+ Répondre à la discussion
Cette discussion est résolue.
Page 2 sur 2 PremièrePremière 12

Discussions similaires

  1. Suppression des doublons dans une variable de type tableau
    Par damsmut dans le forum Général VBA
    Réponses: 2
    Dernier message: 23/07/2019, 10h36
  2. [XL-2003] suppression des doublons dans une Combobox
    Par karim19 dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 08/10/2009, 16h42
  3. [Tableaux] suppression des doublons dans un tableau
    Par hammag dans le forum Langage
    Réponses: 3
    Dernier message: 17/06/2009, 19h13
  4. problème avec la suppression des doublons dans arraylsit
    Par ulysse031 dans le forum Langage
    Réponses: 13
    Dernier message: 04/03/2007, 12h52
  5. Réponses: 13
    Dernier message: 20/11/2006, 17h46

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo