Jak mogę zastąpić pierwsze wystąpienie znaku w każdym słowie?

44

Jak mogę zastąpić pierwsze wystąpienie znaku w każdym słowie?

Powiedz, że mam ten ciąg:

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

I chcę usunąć pierwszy @z każdego słowa, aby w końcu uzyskać końcowy ciąg taki jak ten:

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

Dla wyjaśnienia znaki „@” zawsze pojawiają się razem w każdym słowie, ale mogą znajdować się na początku słowa lub między innymi znakami.

Udało mi się usunąć znak „@”, jeśli występuje on tylko raz, używając odmiany wyrażenia regularnego znalezionego w opcji Usuń podciąg, gdy występuje on raz, ale nie raz, gdy dwa razy z rzędu w pythonie , który używa negatywnego spojrzenia przed i negatywnego spojrzenia:

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

Zobacz wynik:

>>> 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"

Kolejnym krokiem jest zastąpienie litery „@”, gdy występuje ona więcej niż jeden raz. Jest to łatwe, s.replace('@@', '@')usuwając znak „@” z dowolnego miejsca, w którym występuje ponownie.

Zastanawiam się jednak: czy istnieje sposób, aby zrobić to zastąpienie jednym strzałem?

fedorqui „SO przestań szkodzić”
źródło
1
Czy potrzebujesz ściśle wyrażenia regularnego?
Sayandip Dutta
@SayandipDutta w zasadzie tak, ale byłbym również ciekawy innych sposobów, aby zrobić to samo bez wyrażenia regularnego :)
fedorqui „SO przestań szkodzić”
Dla pewności, czy może istnieć ciąg znaków: @Hello@Theregdzie @nie byłoby następujących po sobie?
JvdV
1
@JvdV nie, nie będzie takiego przypadku.
fedorqui „SO przestań krzywdzić”

Odpowiedzi:

51

Zrobiłbym zamianę wyrażenia regularnego według następującego wzoru:

@(@*)

A potem po prostu zastąp pierwszą grupą przechwytywania, która jest ciągłymi symbolami @, minus jeden.

Powinno to uchwycić każde @wystąpienie na początku każdego słowa, czy to słowo na początku, w środku lub na końcu łańcucha.

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

To drukuje:

hello jon i am @here or @@there and want something in 'here
Tim Biegeleisen
źródło
35

Co powiesz na użycie replace('@', '', 1)w wyrażeniu generatora?

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"

Wartość int 1jest opcjonalnym countargumentem.

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

Zwraca kopię łańcucha ze wszystkimi wystąpieniami podciągów starych zastąpionymi przez nowe . Jeśli opcjonalny argument liczba jest podana tylko pierwsze count zdarzenia są zastępowane.

Chłopak
źródło
5
To sprytna sztuczka! Ponieważ trzecim parametrem replace jest replace(search, replace, max_matches), po prostu zastępuje pierwszy z każdego słowa.
fedorqui „SO przestań krzywdzić”
1
@ fedorqui'SOstopharming 'tak, nazywa się count, dodałem opis z dokumentacji.
Guy
2
Uważaj na ten efekt uboczny: jeśli masz kilka białych pól („”), zostaną one utracone i zastąpione jednym „”.
Marc Vanhoomissen
4

Możesz użyć w re.subten sposób:

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)

Spowoduje to:

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

A oto dowód koncepcji:

>>> 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"
>>> 
accdias
źródło
2

Zastanawiałem się nad przypadkami, co, jeśli tylko ostatni znak jest @i nie chcesz go usunąć lub masz określone dozwolone znaki początkowe, wymyślił to:

>>> ' '.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"

Lub załóżmy, że chcesz zastąpić @tylko, jeśli zawiera on pierwsze n znaków

>>> ' '.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"
Sayandip Dutta
źródło
1
# Python3 program to remove the @ from String


def ExceptAtTheRate(string):
    # Split the String based on the space
    arrOfStr = string.split()

    # String to store the resultant String
    res = ""

    # Traverse the words and
    # remove the first @ From every word.
    for a in arrOfStr:
        if(a[0]=='@'):
            res += a[1:len(a)] + " "
        else:
            res += a[0:len(a)] + " "

    return res


# Driver code
string = "hello @jon i am @@here or @@@there and want some@thing in '@here"

print(ExceptAtTheRate(string))

Wynik:

wprowadź opis zdjęcia tutaj

Amar Kumar
źródło
Dzięki! Zauważ, że @ w obrębie @ rzeczy i „@here również powinny zostać usunięte, zgodnie z moimi wymaganiami.
fedorqui „SO przestań krzywdzić”