2

必要な結果が得られる正規表現が機能していますが、必要な安全性が含まれていません。(フールプルーフ)

次のようなパスの一部に一致する正規表現があるとします。

import re
path = "C:/Projects/foo/dev/model/props/furniture/couch/data/fbx"
regex = re.compile("(.+)/dev/model/(.+)/(.+)/data/fbx")
m = regex.search(path)
if m:
    print m.groups()

# ('C:/Projects/foo', 'props/furniture', 'couch')

正規表現の次の部分までの任意の文字に一致するものを、1 つ以上のフォルダーに一致するものに置き換えられるようにしたいと考えています。

簡単にするために、フォルダーをスラッシュで終わる単語文字 (なしまたはそれ以上) として定義するとします。

[\w]*/

そして、それらの 0 から 10 をグループ化したいのですが、どうすればよいでしょうか?

私の心の中で、私は次のようなものを持っていました(これは機能しないことに注意してください!):

# match any number of word characters ending with a slash zero to ten times
([[\w]*/]{0,10})

# match any number of word characters ending with a slash zero to one time
([[\w]*/]?)

編集:

RedBaron と jamylak の回答に基づいて、次のことを思いつきました。

((?:[:\w]+/){0,3})

これにより、スラッシュ「/」で終わる 0 ~ 3 個の [:\w] 文字がグループ化されます。グループの先頭に ?: があると、一致したグループに送り返されません。それでも、それらを組み合わせた外側のグループはそうです。したがって、完全にグループ化された結果のみが返されます。

これに関する唯一の問題は、最後の部分もファイルと一致する可能性があることです。(したがって、スラッシュで終わらないでください。)正規表現から末尾のスラッシュなしでそれを取得することも好みますが、結果の末尾のスラッシュを簡単に削除することもできます。

フィードバックは大歓迎です。これが進むべき道である場合、私はそれを答えとして追加します。

編集:

関連項目:定義済みのフォルダー構造に基づいてフォルダーを検索する

更新/編集:

これまでに与えられたすべての回答に基づいて、さまざまな試みを思いつきましたが、最終的にはすべて非常に遅くなります。

import re
path = "C:/Projects/foo/dev/model/props/furniture/couch/data/fbx"
regex = re.compile(r"""((?:^(?:[\w:]+/?)+)|(?:(?<=/)(?:[\w]+/?)+))/dev/model/""")
print 'search start'
m = regex.search(path)
print 'search done'
if m:
    print 'match', m, m.groups()
else:
    print 'no match'

これを高速化する方法が完全にはわかりません!

4

3 に答える 3

3

正規表現内の[]は、正規表現をグループ化しません。文字クラスを指定するために使用されます。

多分これはうまくいくでしょう-

\w*/{0,10}

グループ化には、()

(\w*/){0,10}

編集

編集した質問に基づいて、ディレクトリ名の0〜3回の出現が一致し、次にファイル名も一致することが必要だと思います。

ファイル名にアルファベットのみ(およびオプションで最大3文字の拡張子)を想定

^((?:[:\w]+/){0,3})(\w+(?:\.\w{1,3})?)?$

これは非常に大きいですが、2つの部分に分けることができます

これはあなたがすでに持っているものです

((?:[:\w]+/){0,3})

そして私が追加するもの

(\w+(?:\.\w{1,3})?)?

これは、最後のオプションのファイル名です。(オプションでない場合は、最後を削除できます?)。ファイル名自体は、アルファベットのみで構成することも、最大3文字の拡張子を付けることもできます。

追加^して、$拍車の一致を停止します

>>> pat=re.compile('^((?:[:\w]+/){0,3})(\w+(?:\.\w{1,3})?)?$')
>>> my_str='fwefw/wfwf/wefwf/dde.cdf'
>>> pat.search(my_str).groups()
('fwefw/wfwf/wefwf/', 'dde.cdf')
>>> my_str='fwefw/dde.cdf'
>>> pat.search(my_str).groups()
('fwefw/', 'dde.cdf')
于 2013-03-21T08:57:28.057 に答える
1

これの代わりに、壊滅的なバックトラッキングが原因で実際​​に非常に遅くなります。

((?:^(?:[\w:]+/?)+)|(?:(?<=/)(?:[\w]+/?)+))/dev/model/

これを試して

(^[\w:]+(?:/\w+)*|(?<=/)\w+(?:/\w+)*)/dev/model/

またはこれ

(^[\w:]+[\w/]*|(?<=/)[\w/]+)/dev/model/

re.match最初に次のようなパターンを使用して文字列を検証するアプローチを検討することをお勧めします。(\w:)?(/\w+)+$

次に、特定の構造がすでに期待できる場合は、より単純な正規表現を使用してデータを抽出できます。

/?([^/]*(?:/[^/]+)*)/dev/model/
于 2013-03-21T21:12:09.987 に答える
0

ここのように[]中に入れることはできません。代わりに、角かっこを使用してグループ化します。[]([[\w]*/]{0,10})

これを試して:

>>> re.match(r'(\w*/){0,10}', 'abc/def/ghi/').group()
'abc/def/ghi/'
于 2013-03-21T08:57:43.267 に答える