0

私はPythonで次の2つの文字列を解析しようとしています:

これが最初の文字列です

s1="< one > < two > < three > here's one attribute < six : 10.3 > < seven : 8.5 > < eight : 90.1 > < nine : 8.7 >"

上記を分割して次のようなリストに格納できるように、reが必要です。ここで、下の新しい行の各項目は、リスト内の特定のインデックスの要素です。

0 one    
1 two 
2 three
3 here's one attribute
4 six : 10.3
5 seven : 8.5
6 eight : 90.1
7 nine : 8.7

これが2番目の文字列です

s2="<one><two><three> an.attribute ::"

同様に、次のようなリストにアイテムを保存する必要があります。

0 one
1 two
2 three
3 an.attribute

これが私がこれまでに試したことです。これは、StackOverflowに投稿した別の質問から得た回答です。

res = re.findall('< (.*?) >', s1)
pprint(res)
index=0
for index in res:
    print index

しかし、それは「ここに1つの属性があります」をスキップします

出力:

['one', 'two', 'three', 'six : 10.3', 'seven : 8.5', 'eight : 90.1', 'nine : 8.7']
one
two
three
six : 10.3
seven : 8.5
eight : 90.1
nine : 8.7

誰か助けてもらえますか?=)

最初の文字列から10.3、8.5、90.1、8.7のような文字列から数値を抽出する方法を誰かが知っているなら、それも素晴らしいでしょう=)

編集:ダンカン私はあなたのコードを試しましたが、私は私がすべきように出力を取得していないようです。どこかでなんらかの間違いをしたと思います。それが何であるか教えてもらえますか?

from __future__ import generators
from pprint import pprint
s2="<one><two><three> an.attribute ::"
s1="< one > < two > < three > here's one attribute < six : 10.3 > < seven : 8.5 > <   eight : 90.1 > < nine : 8.7 >"
def parse(s):
    for t in s.split('<'):
        for u in t.strip().split('>',1):
            if u.strip(): yield u.strip()

list(parse(s1))
list(parse(s2))
pprint(s1)
pprint(s2)

これが私が得ている出力です:

"< one > < two > < three > here's one attribute < six : 10.3 > < seven : 8.5 > < eight : 90.1 > < nine : 8.7 >"
'<one><two><three> an.attribute ::'
4

2 に答える 2

2

これですべてのものを取得できます。必要な正確な出力を得るために、いくつかのifステートメントと微調整を追加できると確信しています

c = 0
m=re.compile('< (\w+) (: ([\d.]+))* *> ([^<]*)')
for r in m.finditer(s1):
    c = c + 1
    (tag,junk,number,attribute)=r.groups()
    print c, attribute

編集:詳細説明

re.compile 行は、使用する正規表現を準備します この正規表現が何をするかを分解するには、最初に ( ) 丸括弧が結果 (r.groups()) で終わる項目をマークしていることを理解する必要があります。

したがって、式 < (\w+) は、< を見つけ、次にスペースを見つけ、次にキャプチャ グループを開始することを意味します キャプチャ グループには、a から z のような 1 つ以上の「単語文字」が含まれます

これがタグの見つけ方です

次のビットは (: ([\d.]+))* です。再びキャプチャ グループが開始されます。次に : が存在する必要があり、次に別のキャプチャ グループが存在する必要があります。角括弧 [] は文字クラスを定義し、\d は数字の一致を表します。。このコンテキストでは、単なるドットです。したがって、クラスは数字またはドットであるすべてのものと一致します。+ は「1 つ以上の前の式」を意味するため、1 つ以上の数字またはドットです。これは数を取得するためです。最後に、丸括弧でキャプチャ グループを閉じた後、アスタリスクがあります * これは、前の式の 0 個以上をキャプチャすることを意味します。これには、前のグループをオプションにする効果があります。すべてのタグに数字があるわけではありません。

そこで正規表現の説明をやめます。正規表現の作成方法を学ぶための優れたリソースがたくさんあります

finditer は単に文字列の正規表現を繰り返し、そこから一致するものを見つけます

この式(tag,junk,number,attribute)=r.groups()は、リストの結果 (r.group) を個々の変数 tag、junk、number、および attribute にコピーすることを意味します。

于 2013-03-13T10:42:50.867 に答える
1

正規表現をまったく使用しない簡単な解決策を次に示します。

def parse(s):
    for t in s.split('<'):
        for u in t.strip().split('>',1):
            if u.strip(): yield u.strip()

>>> list(parse(s1))
['one', 'two', 'three', "here's one attribute", 'six : 10.3', 'seven : 8.5', 'eight : 90.1', 'nine : 8.7']
>>> list(parse("<one><two><three> an.attribute ::"))
['one', 'two', 'three', 'an.attribute ::']

>>> from pprint import pprint
>>> pprint(list(parse(s1)))
['one',
 'two',
 'three',
 "here's one attribute",
 'six : 10.3',
 'seven : 8.5',
 'eight : 90.1',
 'nine : 8.7']

単一のリスト内包表記として記述することもできますが、お勧めしません。

>>> [ u.strip() for t in s1.split('<') for u in t.strip().split('>',1) if u.strip() ]
['one', 'two', 'three', "here's one attribute", 'six : 10.3', 'seven : 8.5', 'eight : 90.1', 'nine : 8.7']
于 2013-03-13T12:14:41.957 に答える