#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 52 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 - markdown
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 ?
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!
... 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
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 52 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 - markdown
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 52 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 - markdown
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.
#!/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
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 52 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 - markdown
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
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... )
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 52 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 - markdown
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 52 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 - markdown
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 52 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 - markdown
Hors ligne