web-dev-qa-db-fra.com

Utiliser regex pour ajouter des zéros non significatifs

Je voudrais ajouter un certain nombre de zéros non significatifs (disons jusqu'à 3) à tous les nombres d'une chaîne. Par exemple:

Entrée: /2009/5/song 01 of 12

Sortie: /2009/0005/song 0001 of 0012

Quelle est la meilleure façon de faire cela avec des expressions régulières?

Modifier:

J'ai choisi la première réponse correcte. Cependant, toutes les réponses valent la peine d'être lues.

27
hpique

Utilisez quelque chose qui prend en charge un rappel afin de pouvoir traiter la correspondance:

>>> r=re.compile(r'(?:^|(?<=[^0-9]))([0-9]{1,3})(?=$|[^0-9])')
>>> r.sub(lambda x: '%04d' % (int(x.group(1)),), 'dfbg345gf345', sys.maxint)
'dfbg0345gf0345'
>>> r.sub(lambda x: '%04d' % (int(x.group(1)),), '1x11x111x', sys.maxint)
'0001x0011x0111x'
>>> r.sub(lambda x: '%04d' % (int(x.group(1)),), 'x1x11x111x', sys.maxint)
'x0001x0011x0111x'
5

En Perl:

s/([0-9]+)/sprintf('%04d',$1)/ge;
28
Snowhare

Un échantillon:

>>> re.sub("(?<!\d)0*(\d{1,3})(?!\d)","000\\1","/2009/5/song 01 of 3")
'/2009/0005/song 0001 of 0003'

Remarque:

  • Cela ne fonctionne que pour les numéros 1 à 9 pour l'instant
  • Ce n'est pas bien tester

Je ne peux pas penser à une seule expression régulière sans utiliser les rappels pour l'instant * (il pourrait y avoir un moyen de le faire).

Voici deux expressions régulières pour traiter cela:

>>> x = "1/2009/5/song 01 of 3 10 100 010 120 1200 abcd"
>>>
>>> x = re.sub("(?<!\d)0*(\d{1,3})(?!\d)","000\\1",x)
#'0001/2009/0005/song 0001 of 0003 00010 000100 00010 000120 1200 abcd'
>>>
>>> re.sub("0+(\d{4})(?!\d)","\\1",x) #strip extra leading zeroes
'0001/2009/0005/song 0001 of 0003 0010 0100 0010 0120 1200 abcd'
2
YOU

Utiliser c#:

string result = Regex.Replace(input, @"\d+", me =>
{
    return int.Parse(me.Value).ToString("0000");
});
1
Alex

Si votre implémentation d'expression régulière ne prend pas en charge les assertions d'anticipation et/ou d'anticipation, vous pouvez également utiliser cette expression régulière:

(^|\D)\d{1,3}(\D|$)

Et remplacez la correspondance par $1 + padLeft($2, 4, "0") + $3$1 est la correspondance du premier groupe et padLeft(str, length, padding) est une fonction qui préfixe str avec padding jusqu'à atteindre la longueur length.

1
Gumbo

<warning> Ceci suppose un intérêt académique, bien sûr, vous devez utiliser des rappels pour le faire clairement et correctement </warning>

Je peux abuser des expressions régulières pour avoir deux zéros non significatifs (saveur .NET):

s = Regex.Replace(s, @".(?=\b\d\b)|(?=\b\d{1,2}\b)", "$&0");

Cela ne fonctionne pas s'il y a un nombre au début de la chaîne. Cela fonctionne en faisant correspondre la largeur à 0 avant un nombre ou le caractère avant un nombre et en les remplaçant par 0.

Je n’ai pas eu la chance de l’étendre à trois zéros en tête, et certainement pas plus.

1
Kobi

Une autre approche:

>>> x
'/2009/5/song 01 of 12'
>>> ''.join([i.isdigit() and i.zfill(4) or i for i in re.split("(?<!\d)(\d+)(?!\d)",x)])
'/2009/0005/song 0001 of 0012'
>>>

Ou:

>>> x
'/2009/5/song 01 of 12'
>>> r=re.split("(?<!\d)(\d+)(?!\d)",x)
>>> ''.join(a+b.zfill(4) for a,b in Zip(r[::2],r[1::2]))
'/2009/0005/song 0001 of 0012'
1
YOU

Un programme Scala valide permettant de remplacer tous les groupes de n chiffres par 4. $$ échappe à la fin de la ligne car $, car nous utilisons StringContext (chaîne préfixée par s).

  (f/:(1 to 3)){case (res,i) =>
     res.replaceAll(s"""(?<=[^\\d]|^)(\\d$i)(?=[^\\d]|$$)""", "0"*(4-i)+"$1")
  }
0
Mikaël Mayer

Voici une solution Perl sans rappel ni récursivité. Il utilise l'extension d'exécution du code Perl regex à la place de la substitution directe (le commutateur e), mais il est très facilement étendu à d'autres langages dépourvus de cette construction. 

#!/usr/bin/Perl

while (<DATA>) {
   chomp;
   print "string:\t\t\t$_\n";
# uncomment if you care about 0000000 case:
#   s/(^|[^\d])0+([\d])/\1\2/g;
#   print "now no leading zeros:\t$_\n";    
   s/(^|[^\d]{1,3})([\d]{1,3})($|[^\d]{1,3})/sprintf "%s%04i%s",$1,$i=$2,$3/ge;
   print "up to 3 leading zeros:\t$_\n";
}
print "\n";

__DATA__
/2009/5/song 01 of 12
/2010/10/song 50 of 99
/99/0/song 1 of 1000
1
01
001
0001
/001/
"02"
0000000000

Sortie:

string:                /2009/5/song 01 of 12
up to 3 leading zeros:  /2009/0005/song 0001 of 0012
string:                /2010/10/song 50 of 99
up to 3 leading zeros:  /2010/0010/song 0050 of 0099
string:                /99/0/song 1 of 1000
up to 3 leading zeros:  /0099/0/song 0001 of 1000
string:                1
up to 3 leading zeros:  0001
string:                01
up to 3 leading zeros:  0001
string:                001
up to 3 leading zeros:  0001
string:                0001
up to 3 leading zeros:  0001
string:                /001/
up to 3 leading zeros:  /0001/
string:                "02"
up to 3 leading zeros:  "0002"
string:                0000000000
up to 3 leading zeros:  0000000000
0
dawg

Combiné dans Xcode:

targetName=[NSString stringWithFormat:@"%05d",number];

Donne 00123 pour le numéro 123

0
Vincent