#1 Le 17/09/2020, à 15:30
- Julie M
[Résolu] Boucle remplacement de caractères et opérations
Bonjour à tous,
Tout d’abord je tiens à préciser que je suis totalement novice en shell. Je cherche à écrire un script me permettant de faire plusieurs modifications sur un gros fichier (15Go compressé)
Exemple de fichier :
1/1 0/1 0/0 1/0 1/1 1/1:0,0.003,0.997 1/1 1/1 1/1 1/1:0,0.042,0.958 1/1 1/1 1/1 1/1 1/1:0,0.001,0.999 1/1 1/1 1/1:0,0.00903,0.99097 1/1 1/1:0,0.042,0.958 1/1
Je dois :
- Remplacer les 1/1 par 2, les 0/1 et 1/0 par 1 et les 0/0 par 0
- Lorsque le format est « 1/1:0,0.042,0.958» je dois effectuer une opération sur les 3 valeurs situées après « 1/1: » . A savoir : 1*première valeur + 1*deuxième valeur + 2*troisième valeur, ce qui donnerait ici 1*0+1*0.042+2*0.958 soit 1.958
Pour l’exemple ci-dessus je devrai obtenir :
2 1 0 1 2 1.997 2 2 2 1.958 2 2 2 2 1.999 2 2 1.99097 2 1.958 2
Est-ce que quelqu’un aurait une solution ?
Merci d’avance
Julie
Dernière modification par Ayral (Le 22/09/2020, à 15:14)
Hors ligne
#2 Le 17/09/2020, à 16:41
- kamaris
Re : [Résolu] Boucle remplacement de caractères et opérations
Avec awk ça devrait être assez rapide, peut-être y a-t-il plus court et rapide que ça :
awk '{gsub("1/1","2"); gsub("1/0|0/1","1"); gsub("0/0","0"); for (i=1;i<=NF;i++) if ($i ~ ":"){sub(".*:","",$i); split($i,a,","); $i=a[1]+a[2]+2*a[3]} print}' fichier
Rq : les espacements entre les champs ne sont pas préservés par cette commande.
Hors ligne
#3 Le 17/09/2020, à 17:22
- pingouinux
Re : [Résolu] Boucle remplacement de caractères et opérations
Bonjour,
Autre solution, moins concise, en python :
$ cat script.py
#!/usr/bin/env python3
import sys, re
rec1=re.compile('(^|\s)([01]/[01])(:[.,\d]+)?($|\s)')
rec2=re.compile('(^|\s)2:(\S+)($|\s)')
def f1(obj):
v1,v2=map(int,obj.group(2).split('/'))
return obj.group(1)+str(v1+v2)+(obj.group(3) if obj.group(3) else "")+obj.group(4)
def f2(obj):
v=tuple(map(float,obj.group(2).split(',')))
return obj.group(1)+str(round(v[0]+v[1]+2*v[2],5))+obj.group(3)
with open(sys.argv[1]) as f: t=f.read()
t=rec1.sub(f1,t)
t=rec2.sub(f2,t)
print(t)
À appeler ainsi
./script.py fichier
Hors ligne
#4 Le 18/09/2020, à 07:43
- Compte supprimé
Re : [Résolu] Boucle remplacement de caractères et opérations
Bonjour,
Juste pour le fun , autre approche avec python et sans expressions rationnelles:
(depuis une string , à modifier en conséquence pour un usage sur fichier)
s = "1/1 0/1 0/0 1/0 1/1 1/1:0,0.003,0.997 1/1 1/1 1/1 1/1:0,0.042,0.958 1/1 1/1 1/1 1/1 1/1:0,0.001,0.999 1/1 1/1 1/1:0,0.00903,0.99097 1/1 1/1:0,0.042,0.958 1/1 "
s= s.split()
def modifie(expression):
if expression == '0/1' or expression == '1/0':
return 1
if expression == "1/1":
return 2
if expression == "0/0":
return 0
for index,expression in enumerate(s):
if ":" in expression:
l_exp = expression.split(":")
_somme = [float(i) for i in l_exp[1].split(",")]
_somme = _somme[0] + _somme[1] + 2*_somme[2]
s[index] = _somme
else:
s[index] = modifie(expression)
print(s)
#5 Le 18/09/2020, à 07:52
- Compte supprimé
Re : [Résolu] Boucle remplacement de caractères et opérations
Si comme le laisse à penser l'exemple, toutes les expressions sont sous la forme "0/0" "1/0" "0/1" .... nous pourrions utiliser un dico à la place des tests
s = "1/1 0/1 0/0 1/0 1/1 1/1:0,0.003,0.997 1/1 1/1 1/1 1/1:0,0.042,0.958 1/1 1/1 1/1 1/1 1/1:0,0.001,0.999 1/1 1/1 1/1:0,0.00903,0.99097 1/1 1/1:0,0.042,0.958 1/1 "
s = s.split()
equivalence = {'0/1':1, '1/0':1, '1/1':2, '0/0':0}
def modifie(expression):
return equivalence[expression]
for index,expression in enumerate(s):
if ":" in expression:
l_exp = expression.split(":")
_somme = [float(i) for i in l_exp[1].split(",")]
_somme = _somme[0] + _somme[1] + 2*_somme[2]
s[index] = _somme
else:
s[index] = modifie(expression)
print(s)
#6 Le 22/09/2020, à 11:10
- Julie M
Re : [Résolu] Boucle remplacement de caractères et opérations
Bonjour kamaris, pingouinux et pseudofab,
Je vous remercie pour vos réponses rapides à mon post. J'ai opté pour la solution de Kamaris et cela fonctionne parfaitement.
Effectivement les espacements entre les champs n'ont pas été préservés, il ne me reste plus qu'à trouver comment ajouter des tabulations comme délimitateur de champs.
Julie
Hors ligne
#7 Le 22/09/2020, à 15:13
- Ayral
Re : [Résolu] Boucle remplacement de caractères et opérations
Modération : puisque tu as eu la réponse à ta question, il est d'usage de la passer en Résolu en modifiant ton premier message puis en rajoutant l'expression [Résolu] au début du sujet. Je le fais pour gagner du temps.
Pour mettre les retours de commande entre deux balises code, les explications sont là : https://forum.ubuntu-fr.org/viewtopic.php?id=1614731
Blog d'un retraité
Site de graphisme du fiston Loïc
Ubuntu 22.04 LTS sur un Thinkpad W540
Hors ligne
#8 Le 22/09/2020, à 16:51
- kamaris
Re : [Résolu] Boucle remplacement de caractères et opérations
Effectivement les espacements entre les champs n'ont pas été préservés, il ne me reste plus qu'à trouver comment ajouter des tabulations comme délimitateur de champs.
Pour ça, il te suffit d'ajouter BEGIN{OFS="\t"} au début du programme awk, soit au final :
awk 'BEGIN{OFS="\t"} {gsub("1/1","2"); gsub("1/0|0/1","1"); gsub("0/0","0"); for (i=1;i<=NF;i++) if ($i ~ ":"){sub(".*:","",$i); split($i,a,","); $i=a[1]+a[2]+2*a[3]} print}' fichier
S'il avait fallu retrouver un espacement particulier entre chaque couple de champs, ça aurait été un peu plus compliqué.
Hors ligne