6

次の形式の文字列があります。

t='@abc @def Hello this part is text'

私はこれを手に入れたい:

l=["abc", "def"] 
s='Hello this part is text'

これは私がしました:

a=t[t.find(' ',t.rfind('@')):].strip()
s=t[:t.find(' ',t.rfind('@'))].strip()
b=a.split('@')
l=[i.strip() for i in b][1:]

ほとんどの部分で機能しますが、テキスト部分に「@」が含まれていると失敗します。例:いつ:

t='@abc @def My email is red@hjk.com'

失敗します。@namesは最初にあり、@ namesの後にテキストがあり、@が含まれている可能性があります。

明らかに、最初にスペースを追加して、「@」のない最初の単語を見つけることができます。しかし、それはエレガントな解決策ではないようです。

これを解決するためのPythonの方法は何ですか?

4

7 に答える 7

13

MrTopf の努力を恥知らずに構築する:

import re
rx = re.compile("((?:@\w+ +)+)(.*)")
t='@abc   @def  @xyz Hello this part is text and my email is foo@ba.r'
a,s = rx.match(t).groups()
l = re.split('[@ ]+',a)[1:-1]
print l
print s

プリント:

['abc', 'def', 'xyz']
こんにちは、この部分はテキストで、私のメールアドレスは foo@ba.r です


hasen jから説明を求められたので、これがどのように機能するかを明確にしましょう。

/@\w+ +/

単一のタグ (@ の後に少なくとも 1 つの英数字が続くか、または _ の後に少なくとも 1 つの空白文字が続く) に一致します。+ は貪欲なので、スペースが複数ある場合はすべて取得します。

これらのタグの任意の数に一致させるには、tag のパターンにプラス (1 つ以上のもの) を追加する必要があります。したがって、括弧でグループ化する必要があります。

/(@\w+ +)+/

これは 1 つ以上のタグに一致し、貪欲であるため、それらすべてに一致します。ただし、これらの括弧は現在、キャプチャ グループをいじっているため、それらを匿名グループにすることで元に戻します。

/(?:@\w+ +)+/

最後に、それをキャプチャ グループにし、別のグループを追加して残りを一掃します。

/((?:@\w+ +)+)(.*)/

要約する最後の内訳:

((?:@\w+ +)+)(.*)
 (?:@\w+ +)+
 (  @\w+ +)
    @\w+ +

これを見直して改善したことに注意してください - \w をセットにする必要はなく、タグ間に複数のスペースを使用できるようになりました。ありがとう、hasen-j!

于 2009-02-17T19:32:42.337 に答える
7
t='@abc @def Hello this part is text'

words = t.split(' ')

names = []
while words:
    w = words.pop(0)
    if w.startswith('@'):
        names.append(w[1:])
    else:
        break

text = ' '.join(words)

print names
print text
于 2009-02-17T19:32:42.570 に答える
5

これはどう:

  1. スペースによる分割。
  2. foreach ワード、チェック

    2.1. 単語が @ で始まる場合、最初のリストにプッシュ

    2.2. それ以外の場合は、残りの単語をスペースで結合します。

于 2009-02-17T19:03:38.083 に答える
3
 [i.strip('@') for i in t.split(' ', 2)[:2]]     # for a fixed number of @def
 a = [i.strip('@') for i in t.split(' ') if i.startswith('@')]
 s = ' '.join(i for i in t.split(' ') if not i.startwith('@'))
于 2009-02-17T18:37:22.470 に答える
3

正規表現を使用することもできます。

import re
rx = re.compile("@([\w]+) @([\w]+) (.*)")
t='@abc @def Hello this part is text and my email is foo@ba.r'
a,b,s = rx.match(t).groups()

ただし、これはすべて、データがどのように見えるかによって異なります。そのため、調整する必要があるかもしれません。基本的に、() を介してグループを作成し、それらで何が許可されているかを確認します。

于 2009-02-17T18:40:23.897 に答える
1

以下は、split() を使用し、正規表現を使用しない別のバリエーションです。

t='@abc @def My email is red@hjk.com'
tags = []
words = iter(t.split())

# iterate over words until first non-tag word
for w in words:
  if not w.startswith("@"):
    # join this word and all the following
    s = w + " " + (" ".join(words))
    break
  tags.append(w[1:])
else:
  s = "" # handle string with only tags

print tags, s

これは、正規表現を使用して最初のスペースとその後に @ 以外の文字が続く、より短いがおそらく少し不可解なバージョンです。

import re
t = '@abc @def My email is red@hjk.com @extra bye'
m = re.search(r"\s([^@].*)$", t)
tags = [tag[1:] for tag in t[:m.start()].split()]
s = m.group(1)
print tags, s # ['abc', 'def'] My email is red@hjk.com @extra bye

タグやテキストがない場合、これは正しく機能しません。形式が指定されていません。検証するには、さらに多くのテスト ケースを提供する必要があります。

于 2009-02-18T23:14:31.793 に答える