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 05/07/2016, à 08:21

Le Goss

[Résolu] bash: réduction nombre de lignes commençant par même chaîne

Bonjour à tous,
Voici mon fichier

abc1.1
abc1.9
abc1.10
abc1.11
abc2.3
abc2.5
efg10.2
efg10.3
efg10.4
efg10.6
hij15.5

Toutes les lignes sont toute du type:

- une série de 3 caractères alpha-numériques
- un nombre à 1 ou plusieurs chiffres
- un point
- un nombre à 1 ou plusieurs chiffres

Je cherche à obtenir

abc1.1, 9-11, 2.3, 5
efg10.2-4, 6
hij15.5

J'avoue ne pas avoir la moindre idée de la direction dans laquelle il faut chercher...
Il doit y avoir du cut ou du awk dans l'air. Mais bon. Je cale.
Merci pour votre aide!
Cordialement

Dernière modification par Le Goss (Le 05/07/2016, à 21:47)


Si je pose une question sur le forum, ce n'est pas par paresse ou pour faire faire "mes devoirs"; c'est par ignorance: j'ai 51 berges. Et, par principe, je préfère être traité d'ignare que de fainéant.
Samsung i7-3630QM CPU @ 2.40GHz × 8 - 64 bits - RAM 7,7 Gio - DD 976 Go - Bodhi 6.0.0 Ubuntu 20.04
Allergique au wysiwyg; traitement à vie: Lilypond - LaTeX - txt2tags

Hors ligne

#2 Le 05/07/2016, à 08:46

Shanx

Re : [Résolu] bash: réduction nombre de lignes commençant par même chaîne

Salut,
C'est obligatoirement en bash ? big_smile
Parce qu'en Python (Python 3 en l'occurrence) c'est très facile :

#!/usr/bin/env python3

import sys

result = {}
    
with open(sys.argv[1]) as f:
    for l in f:
        if not l:
            continue
        l=l.rstrip()
        if l[:3] not in result:
            result[l[:3]]=[l[3:]]
        else:
            result[l[:3]].append(l[3:])
            
for r in result:
    print(r, ", ".join(result[r]), sep='')

Usage :

python3 script.py fichier.txt

Une version encore plus simple si les préfixes (les 3 premiers caractères alphanumériques) sont déjà triés :

#!/usr/bin/env python3

import sys

result = {}
prefixe = ""
    
with open(sys.argv[1]) as f:
    for l in f:
        if not l:
            continue
        l=l.rstrip()
        if not prefixe == l[:3]:
            prefixe = l[:3]
            sys.stdout.write("\n"+l)
        else:
            sys.stdout.write(", "+l[3:])
print("\n")

Dernière modification par Shanx (Le 05/07/2016, à 08:53)


Mes randos : grande traversées des Alpes, de l'Islande, de la Corse, du Japon (en vélo), etc.
Traversée des États-Unis à pied

Hors ligne

#3 Le 05/07/2016, à 09:11

Le Goss

Re : [Résolu] bash: réduction nombre de lignes commençant par même chaîne

Merci pour ta réponse!

Shanx a écrit :

... en Python (Python 3 en l'occurrence) c'est très facile

python3 script.py fichier.txt

Tout dépend de quel point de vue on se place lol
Je m'étais motivé il y a quelques mois à m'y mettre, mais j'ai vite trouvé la syntaxe peut attrayante et les finalités peu évidentes.
Mais il faudra bien qu'un jour ou l'autre je me lance... vraiment.


Si je pose une question sur le forum, ce n'est pas par paresse ou pour faire faire "mes devoirs"; c'est par ignorance: j'ai 51 berges. Et, par principe, je préfère être traité d'ignare que de fainéant.
Samsung i7-3630QM CPU @ 2.40GHz × 8 - 64 bits - RAM 7,7 Gio - DD 976 Go - Bodhi 6.0.0 Ubuntu 20.04
Allergique au wysiwyg; traitement à vie: Lilypond - LaTeX - txt2tags

Hors ligne

#4 Le 05/07/2016, à 09:21

Le Goss

Re : [Résolu] bash: réduction nombre de lignes commençant par même chaîne

Je viens d'essayer ton script.
J'avais déjà obtenu le même résultat en bash:

abc1.1, 1.9, 1.10, 1.11, 2.3, 2.5
efg10.2, 10.3, 10.4, 10.6
hij15.5

et non

abc1.1, 9-11, 2.3, 5
efg10.2-4, 6
hij15.5

Si je pose une question sur le forum, ce n'est pas par paresse ou pour faire faire "mes devoirs"; c'est par ignorance: j'ai 51 berges. Et, par principe, je préfère être traité d'ignare que de fainéant.
Samsung i7-3630QM CPU @ 2.40GHz × 8 - 64 bits - RAM 7,7 Gio - DD 976 Go - Bodhi 6.0.0 Ubuntu 20.04
Allergique au wysiwyg; traitement à vie: Lilypond - LaTeX - txt2tags

Hors ligne

#5 Le 05/07/2016, à 12:09

Shanx

Re : [Résolu] bash: réduction nombre de lignes commençant par même chaîne

EDIT : finalement je te donne la réponse complète. Tu me citeras dans ton devoir. tongue

#!/usr/bin/env python3

import sys
from itertools import groupby, count

result = {}
        
def as_range(iterable):
    l = list(iterable)
    if len(l) > 1:
        return '{0}-{1}'.format(l[0], l[-1])
    else:
        return '{0}'.format(l[0])
    
with open(sys.argv[1]) as f:
    for l in f:
        if not l:
            continue
        l=l.rstrip()
        ent, frac = l[3:].split(".")
        frac=int(frac)
        if l[:3] not in result:
            result[l[:3]]={ent:[frac]}
        else:
            if ent not in result[l[:3]]:
                result[l[:3]][ent]=[frac]
            else:
                result[l[:3]][ent].append(frac)

for r in sorted(result):
    print(r, end="")
    i=False
    for k in sorted(result[r]):
        if i: print(", ", end="")
        i=not(i)
        print(k,end=".")
        print(', '.join(as_range(g) for _, g in groupby(result[r][k], key=lambda n, c=count(): n-next(c))), end="")
    sys.stdout.write("\n")

Dernière modification par Shanx (Le 05/07/2016, à 12:24)


Mes randos : grande traversées des Alpes, de l'Islande, de la Corse, du Japon (en vélo), etc.
Traversée des États-Unis à pied

Hors ligne

#6 Le 05/07/2016, à 13:28

Le Goss

Re : [Résolu] bash: réduction nombre de lignes commençant par même chaîne

Shanx a écrit :

EDIT : finalement je te donne la réponse complète. Tu me citeras dans ton devoir.

Mon brave, je vais vers mes 45 balais. Mes études sont donc loin derrière moi.
Et à cette époque où j'aurais pu plancher sur ce type de devoir, on n'en n'était qu'aux MO5 et TO7, au temps merveilleux des bandes magnétiques et de la bande FM.
Comme ce n'est pas la première fois qu'on me suspecte de vouloir faire faire aux autres mes "devoirs", je vais ajouter un petit message dans ma signature.

Car si je demande de l'aide ici, ce n'est pas par paresse. Etant méridional, je pourrais légitimement m'y complaire.
Non, c'est juste par ignorance ou incompétence. Ben oui.
Merci pour ta réponse, ton aide et ta patience à mon égard.
Cordialement


Si je pose une question sur le forum, ce n'est pas par paresse ou pour faire faire "mes devoirs"; c'est par ignorance: j'ai 51 berges. Et, par principe, je préfère être traité d'ignare que de fainéant.
Samsung i7-3630QM CPU @ 2.40GHz × 8 - 64 bits - RAM 7,7 Gio - DD 976 Go - Bodhi 6.0.0 Ubuntu 20.04
Allergique au wysiwyg; traitement à vie: Lilypond - LaTeX - txt2tags

Hors ligne

#7 Le 05/07/2016, à 13:38

Shanx

Re : [Résolu] bash: réduction nombre de lignes commençant par même chaîne

Le Goss a écrit :
Shanx a écrit :

EDIT : finalement je te donne la réponse complète. Tu me citeras dans ton devoir.

Mon brave, je vais vers mes 45 balais. Mes études sont donc loin derrière moi.
Et à cette époque où j'aurais pu plancher sur ce type de devoir, on n'en n'était qu'aux MO5 et TO7, au temps merveilleux des bandes magnétiques et de la bande FM.
Comme ce n'est pas la première fois qu'on me suspecte de vouloir faire faire aux autres mes "devoirs", je vais ajouter un petit message dans ma signature.

T'inquiètes, je savais que c'était pas pour ça (des devoirs début juillet... tongue )

Non, c'est juste par ignorance ou incompétence. Ben oui.
Merci pour ta réponse, ton aide et ta patience à mon égard.
Cordialement

Du coup c'est bon ?


Mes randos : grande traversées des Alpes, de l'Islande, de la Corse, du Japon (en vélo), etc.
Traversée des États-Unis à pied

Hors ligne

#8 Le 05/07/2016, à 13:52

Le Goss

Re : [Résolu] bash: réduction nombre de lignes commençant par même chaîne

C'est tout bon, sauf que le script semble tout ranger par ordre alphabétique.
Comme tu le dis pour ton 2e code: "les préfixes (les 3 premiers caractères alphanumériques) sont déjà triés".
Et ils doivent apparaître précisément dans cet ordre.


Si je pose une question sur le forum, ce n'est pas par paresse ou pour faire faire "mes devoirs"; c'est par ignorance: j'ai 51 berges. Et, par principe, je préfère être traité d'ignare que de fainéant.
Samsung i7-3630QM CPU @ 2.40GHz × 8 - 64 bits - RAM 7,7 Gio - DD 976 Go - Bodhi 6.0.0 Ubuntu 20.04
Allergique au wysiwyg; traitement à vie: Lilypond - LaTeX - txt2tags

Hors ligne

#9 Le 05/07/2016, à 13:55

Shanx

Re : [Résolu] bash: réduction nombre de lignes commençant par même chaîne

Ah oui. C'est parce que j'utilise des dictionnaires (avec sorted). Il faudrait passer aux tuples pour corriger ça.

EDIT : je n'ai pas le temps de le faire maintenant.

Dernière modification par Shanx (Le 05/07/2016, à 13:58)


Mes randos : grande traversées des Alpes, de l'Islande, de la Corse, du Japon (en vélo), etc.
Traversée des États-Unis à pied

Hors ligne

#10 Le 05/07/2016, à 19:49

pingouinux

Re : [Résolu] bash: réduction nombre de lignes commençant par même chaîne

Bonsoir,
Regarde si ça te convient. C'est du python aussi, mais avec une méthode différente de celle de Shanx #5 (qui marchait d'ailleurs très bien sur ton cas test en #1).

import sys, re

with open(sys.argv[1],'r') as f:
   bas0=''; s=''; lsts=[]; lst=[]
   for lig in f:
      k=re.match('(\D+)(\d+)\.(.*)',lig)
      if k:
         base,num,d=k.groups(); d=int(d)
         if base!=bas0:
            if s: print(s[:-2])
            s="%s"%base; num0=''; bas0=base
         if num!=num0: s+="%s.%s ,"%(num,d); num0=num
         else:
            if d==d0+1:
               if re.search('-\d+, $',s):
                  s=s.rstrip('[, 0123456789]')
                  s="%s-%s, "%(s[:-1],d)
               else: s="%s-%s, "%(s[:-2],d)
            else: s+="%s, "%d
         d0=d
   print("%s"%s[:-2])

Hors ligne

#11 Le 05/07/2016, à 21:08

Le Goss

Re : [Résolu] bash: réduction nombre de lignes commençant par même chaîne

Merci pour le script!
Voici le résultat:

efg10.2-4, 6
abc1.1 ,9-11, 2.3 ,5
hij15.6

2 remarques:
- certaines virgules ont leur espace avant et non après, et le script m'est hermétique pour que je puisse y remédier
- si, comme précisé au début, les 3 premiers caractères présentent 1 ou plusieurs chiffres, le script zappe les lignes correspondantes.


Si je pose une question sur le forum, ce n'est pas par paresse ou pour faire faire "mes devoirs"; c'est par ignorance: j'ai 51 berges. Et, par principe, je préfère être traité d'ignare que de fainéant.
Samsung i7-3630QM CPU @ 2.40GHz × 8 - 64 bits - RAM 7,7 Gio - DD 976 Go - Bodhi 6.0.0 Ubuntu 20.04
Allergique au wysiwyg; traitement à vie: Lilypond - LaTeX - txt2tags

Hors ligne

#12 Le 05/07/2016, à 21:23

pingouinux

Re : [Résolu] bash: réduction nombre de lignes commençant par même chaîne

- certaines virgules ont leur espace avant et non après, et le script m'est hermétique pour que je puisse y remédier

Je ne l'avais pas vu, c'était un faute de frappe.

- si, comme précisé au début, les 3 premiers caractères présentent 1 ou plusieurs chiffres, le script zappe les lignes correspondantes.

J'avais en effet mal lu.

Tout devrait être corrigé

import sys, re

with open(sys.argv[1],'r') as f:
   bas0=''; s=''; lsts=[]; lst=[]
   for lig in f:
      k=re.match('(.{3})(\d+)\.(.*)',lig)
      if k:
         base,num,d=k.groups(); d=int(d)
         if base!=bas0:
            if s: print(s[:-2])
            s="%s"%base; num0=''; bas0=base
         if num!=num0: s+="%s.%s, "%(num,d); num0=num
         else:
            if d==d0+1:
               if re.search('-\d+, $',s):
                  s=s.rstrip('[, 0123456789]')
                  s="%s-%s, "%(s[:-1],d)
               else: s="%s-%s, "%(s[:-2],d)
            else: s+="%s, "%d
         d0=d
   print("%s"%s[:-2])

Hors ligne

#13 Le 05/07/2016, à 21:46

Le Goss

Re : [Résolu] bash: réduction nombre de lignes commençant par même chaîne

Yessssssssssssssssssssssssssssssssssss!
C'est parfait!
Merci à vous deux.
Sujet résolu.


Si je pose une question sur le forum, ce n'est pas par paresse ou pour faire faire "mes devoirs"; c'est par ignorance: j'ai 51 berges. Et, par principe, je préfère être traité d'ignare que de fainéant.
Samsung i7-3630QM CPU @ 2.40GHz × 8 - 64 bits - RAM 7,7 Gio - DD 976 Go - Bodhi 6.0.0 Ubuntu 20.04
Allergique au wysiwyg; traitement à vie: Lilypond - LaTeX - txt2tags

Hors ligne