Comment puis-je remplacer la première occurrence d'un caractère dans chaque mot?

Disons que j'ai cette chaîne:

hello @jon i am @@here or @@@there and want some@thing in '@here"
#     ^         ^^        ^^^                   ^          ^ 

Et je veux supprimer le premier @ sur chaque mot, afin que je finisse par avoir une chaîne finale comme celle-ci:

hello jon i am @here or @@there and want something in 'here
#     ^        ^        ^^                   ^         ^

Pour plus de précision, les caractères "@" apparaissent toujours ensemble dans chaque mot, mais peuvent être au début du mot ou entre d'autres caractères.

J'ai réussi à supprimer le caractère "@" s'il se produit une seule fois en utilisant une variante de l'expression régulière que j'ai trouvée dans Supprimer la sous-chaîne lorsqu'elle se produit une fois , mais pas deux fois de suite en python, qui utilise un lookahead négatif et un lookbehind négatif:

@(?!@)(?<!@@)

Voir la sortie:

>>> s = "hello @jon i am @@here or @@@there and want some@thing in '@here"
>>> re.sub(r'@(?!@)(?<!@@)', '', s)
"hello jon i am @@here or @@@there and want something in 'here"

La prochaine étape consiste donc à remplacer le "@" lorsqu'il se produit plusieurs fois. C'est facile en faisant s.replace('@@', '@') pour supprimer le "@" de partout où il se reproduit.

Cependant, je me demande: existe-t-il un moyen de faire ce remplacement en une seule fois?

44
fedorqui 'SO stop harming' 25 févr. 2020 à 09:13

5 réponses

Meilleure réponse

Je ferais un remplacement regex sur le modèle suivant:

@(@*)

Et puis il suffit de remplacer par le premier groupe de capture, qui est tous des symboles @ continus, moins un.

Cela devrait capturer chaque @ survenant au début de chaque mot, que ce soit au début, au milieu ou à la fin de la chaîne.

inp = "hello @jon i am @@here or @@@there and want some@thing in '@here"
out = re.sub(r"@(@*)", '\\1', inp)
print(out)

Cela imprime:

hello jon i am @here or @@there and want something in 'here
36
Tim Biegeleisen 25 févr. 2020 à 06:22

Vous pouvez utiliser re.sub comme ceci:

import re

s = "hello @jon i am @@here or @@@there and want some@thing in '@here"
s = re.sub('@(\w)', r'\1', s)
print(s)

Cela se traduira par:

"hello jon i am @here or @@there and want something in 'here"

Et voici une preuve de concept:

>>> import re
>>> s = "hello @jon i am @@here or @@@there and want some@thing in '@here"
>>> re.sub('@(\w)', r'\1', s)
"hello jon i am @here or @@there and want something in 'here"
>>> 
3
accdias 25 févr. 2020 à 06:37

DEMO

(?<!@)@

Vous pouvez essayer ça. Voir la démo.

2
vks 25 févr. 2020 à 07:10

Que diriez-vous d'utiliser replace('@', '', 1) dans une expression de générateur?

string = 'hello @jon i am @@here or @@@there and want some@thing in "@here"'
result = ' '.join(s.replace('@', '', 1) for s in string.split(' '))

# output: hello jon i am @here or @@there and want something in "here"

La valeur int de 1 est l'argument facultatif count.

str.replace(old, new[, count])

Renvoyer une copie de la chaîne avec tous occurrences de sous-chaîne ancienne remplacée par nouvelle . Si l'argument facultatif count est donné, seules les premières occurrences de count sont remplacées.

27
wjandrea 26 févr. 2020 à 21:19

Était en train de réfléchir aux cas si seulement le dernier caractère était @ et que vous ne vouliez pas le supprimer, ou si vous aviez des caractères de démarrage autorisés spécifiques, est venu avec ceci:

>>> ' '.join([s_.replace('@', '', 1) if s_[0] in ["'", "@"] else s_ for s_ in s.split()])
"hello jon i am @here or @@there and want some@thing in 'here"

Ou, supposons que vous souhaitiez remplacer @ uniquement s'il est composé des n premiers caractères

>>> ' '.join([s_.replace('@', '', 1) if s_.find('@') in range(2) else s_ for s_ in s.split()])
"hello jon i am @here or @@there and want some@thing in 'here"
1
Sayandip Dutta 25 févr. 2020 à 06:32