3

ディレクトリのように見える変数のリストを照合したいのですが、例:

Same/Same2/Foot/Ankle/Joint/Actuator/Sensor/Temperature/Value=4.123
Same/Same2/Battery/Name=SomeString
Same/Same2/Home/Land/Some/More/Stuff=0.34

「サブディレクトリ」の長さは、上限(9を超える)を持つ可変です。上記で「同じ」と名付けた最初のサブディレクトリを除くすべてのサブディレクトリをグループ化します。

私が思いつくことができる最高のものは次のとおりです。

^(?:([^/]+)/){4,8}([^/]+)=(.*)

すでに4〜8個のサブディレクトリを検索しますが、最後のサブディレクトリのみをグループ化します。なんで?グループ数量詞を使用するより良い解決策はありますか?

編集:解決しました。代わりにsplit()を使用します。

4

4 に答える 4

2

私はおそらくあなたが何をしたいのかを正確に誤解しましたが、正規表現なしでそれを行う方法は次のとおりです。

for entry in list_of_vars:
    key, value = entry.split('=')
    key_components = key.split('/')
    if 4 <= len(key_components) <= 8:
        # here the actual work is done
        print "%s=%s" % ('_'.join(key_components[1:]).upper(), value)
于 2011-07-24T12:47:25.417 に答える
2
import re

regx = re.compile('(?:(?<=\A)|(?<=/)).+?(?=/|\Z)')


for ss in ('Same/Same2/Foot/Ankle/Joint/Actuator/Sensor/Temperature/Value=4.123',
           'Same/Same2/Battery/Name=SomeString',
           'Same/Same2/Home/Land/Some/More/Stuff=0.34'):

    print ss
    print regx.findall(ss)
    print

編集1

これで、取得したいものに関する詳細情報が得られました(_ "Same / Same2 / Battery / Name=SomeStringがSAME2_BATTERY_NAME=SomeString" _になります)より良いソリューションを提案できます:正規表現またはsplit()、+ replace( )。

import re
from os import sep

sep2 = r'\\' if sep=='\\' else '/'

pat = '^(?:.+?%s)(.+$)' % sep2
print 'pat==%s\n' % pat

ragx = re.compile(pat)

for ss in ('Same\Same2\Foot\Ankle\Joint\Actuator\Sensor\Temperature\Value=4.123',
           'Same\Same2\Battery\Name=SomeString',
           'Same\Same2\Home\Land\Some\More\Stuff=0.34'):

    print ss
    print ragx.match(ss).group(1).replace(sep,'_')
    print ss.split(sep,1)[1].replace(sep,'_')
    print

結果

pat==^(?:.+?\\)(.+$)

Same\Same2\Foot\Ankle\Joint\Actuator\Sensor\Temperature\Value=4.123
Same2_Foot_Ankle_Joint_Actuator_Sensor_Temperature_Value=4.123
Same2_Foot_Ankle_Joint_Actuator_Sensor_Temperature_Value=4.123

Same\Same2\Battery\Name=SomeString
Same2_Battery_Name=SomeString
Same2_Battery_Name=SomeString

Same\Same2\Home\Land\Some\More\Stuff=0.34
Same2_Home_Land_Some_More_Stuff=0.34
Same2_Home_Land_Some_More_Stuff=0.34

編集2

あなたのコメントを読み直して、私はあなたが「=」記号の前にあるがその後にはない文字列の部分を上に置きたいということを考慮に入れていなかったことに気づきました。

したがって、この要件に答える3つのメソッドを公開するこの新しいコード。あなたはあなたが好むものを選ぶでしょう:

import re

from os import sep
sep2 = r'\\' if sep=='\\' else '/'



pot = '^(?:.+?%s)(.+?)=([^=]*$)' % sep2
print 'pot==%s\n' % pot
rogx = re.compile(pot)

pet = '^(?:.+?%s)(.+?(?==[^=]*$))' % sep2
print 'pet==%s\n' % pet
regx = re.compile(pet)


for ss in ('Same\Same2\Foot\Ankle\Joint\Sensor\Value=4.123',
           'Same\Same2\Battery\Name=SomeString',
           'Same\Same2\Ocean\Atlantic\North=',
           'Same\Same2\Maths\Addition\\2+2=4\Simple=ohoh'):
    print ss + '\n' + len(ss)*'-'

    print 'rogx groups  '.rjust(32),rogx.match(ss).groups()

    a,b = ss.split(sep,1)[1].rsplit('=',1)
    print 'split split  '.rjust(32),(a,b)
    print 'split split join upper replace   %s=%s' % (a.replace(sep,'_').upper(),b)

    print 'regx split group  '.rjust(32),regx.match(ss.split(sep,1)[1]).group()
    print 'regx split sub  '.rjust(32),\
          regx.sub(lambda x: x.group(1).replace(sep,'_').upper(), ss)
    print

結果、Windowsプラットフォームで

pot==^(?:.+?\\)(.+?)=([^=]*$)

pet==^(?:.+?\\)(.+?(?==[^=]*$))

Same\Same2\Foot\Ankle\Joint\Sensor\Value=4.123
----------------------------------------------
                   rogx groups   ('Same2\\Foot\\Ankle\\Joint\\Sensor\\Value', '4.123')
                   split split   ('Same2\\Foot\\Ankle\\Joint\\Sensor\\Value', '4.123')
split split join upper replace   SAME2_FOOT_ANKLE_JOINT_SENSOR_VALUE=4.123
              regx split group   Same2\Foot\Ankle\Joint\Sensor\Value
                regx split sub   SAME2_FOOT_ANKLE_JOINT_SENSOR_VALUE=4.123

Same\Same2\Battery\Name=SomeString
----------------------------------
                   rogx groups   ('Same2\\Battery\\Name', 'SomeString')
                   split split   ('Same2\\Battery\\Name', 'SomeString')
split split join upper replace   SAME2_BATTERY_NAME=SomeString
              regx split group   Same2\Battery\Name
                regx split sub   SAME2_BATTERY_NAME=SomeString

Same\Same2\Ocean\Atlantic\North=
--------------------------------
                   rogx groups   ('Same2\\Ocean\\Atlantic\\North', '')
                   split split   ('Same2\\Ocean\\Atlantic\\North', '')
split split join upper replace   SAME2_OCEAN_ATLANTIC_NORTH=
              regx split group   Same2\Ocean\Atlantic\North
                regx split sub   SAME2_OCEAN_ATLANTIC_NORTH=

Same\Same2\Maths\Addition\2+2=4\Simple=ohoh
-------------------------------------------
                   rogx groups   ('Same2\\Maths\\Addition\\2+2=4\\Simple', 'ohoh')
                   split split   ('Same2\\Maths\\Addition\\2+2=4\\Simple', 'ohoh')
split split join upper replace   SAME2_MATHS_ADDITION_2+2=4_SIMPLE=ohoh
              regx split group   Same2\Maths\Addition\2+2=4\Simple
                regx split sub   SAME2_MATHS_ADDITION_2+2=4_SIMPLE=ohoh
于 2011-07-24T12:55:31.760 に答える
1

スプリットを使用しますか?

>>> p='Same/Same2/Foot/Ankle/Joint/Actuator/Sensor/Temperature/Value=4.123'
>>> p.split('/')
['Same', 'Same2', 'Foot', 'Ankle', 'Joint', 'Actuator', 'Sensor', 'Temperature', 'Value=4.123']

また、そのキー/値のペアが必要な場合は、次のようなことを行うことができます...

>>> s = p.split('/')
>>> s[-1].split('=')
['Value', '4.123']
于 2011-07-24T12:45:07.073 に答える
1

テーマのバリエーションがいくつかあります。一つには、私は常にregexenが保守不可能な点で不可解であることに気付いたので、pyparsingモジュールを作成しました。私の頭の中では、あなたのコードを見て、「ああ、それは'/'で区切られた文字列、'='記号、そしてある種の右辺値のリストだ」と思います。そして、それはかなり直接、構文解析パーサー定義コードに変換されます。パーサーのあちこちに名前を追加することで(「キー」と「値」、正規表現の名前付きグループに似ています)、出力は非常に簡単に処理されます。

data="""\
Same/Same2/Foot/Ankle/Joint/Actuator/Sensor/Temperature/Value=4.123
Same/Same2/Battery/Name=SomeString
Same/Same2/Home/Land/Some/More/Stuff=0.34""".splitlines()

from pyparsing import Word, alphas, alphanums, Word, nums, QuotedString, delimitedList

wd = Word(alphas, alphanums)
number = Word(nums+'+-', nums+'.').setParseAction(lambda t:float(t[0]))
rvalue = wd | number | QuotedString('"')

defn = delimitedList(wd, '/')('key') + '=' + rvalue('value')

for d in data:
    result = defn.parseString(d)

次に、これらすべての変数名を定義するというあなたのアプローチに疑問を投げかけます。データに基づいてその場で変数名を作成することは、かなりよく認識されているコードの臭いです(必ずしも悪いわけではありませが、このアプローチを再考することをお勧めします)。再帰的なdefaultdictを使用してナビゲート可能な構造を作成し、「「Same2」のサブ要素であるすべてのエントリ(この場合は「Foot」、「Battery」、「Home」)を検索するなどの操作を簡単に実行できるようにしました。 --locals()にあるような変数名のコレクションをふるいにかける場合、この種の作業はより困難になります。これらの名前を再解析してキー階層を再構築することになります。

from collections import defaultdict

class recursivedefaultdict(defaultdict):
    def __init__(self, attrFactory=int):
        self.default_factory = lambda : type(self)(attrFactory)
        self._attrFactory = attrFactory
    def __getattr__(self, attr):
        newval = self._attrFactory()
        setattr(self, attr, newval)
        return newval

table = recursivedefaultdict()

# parse each entry, and accumulate into hierarchical dict
for d in data:
    # use pyparsing parser, gives us key (list of names) and value
    result = defn.parseString(d)
    t = table
    for k in result.key[:-1]:
        t = t[k]
    t[result.key[-1]] = result.value


# recursive method to iterate over hierarchical dict    
def showTable(t, indent=''):
    for k,v in t.items():
        print indent+k,
        if isinstance(v,dict):
            print
            showTable(v, indent+'  ')
        else:
            print v

showTable(table)

プリント:

Same
  Same2
    Foot
      Ankle
        Joint
          Actuator
            Sensor
              Temperature
                Value 4.123
    Battery
      Name SomeString
    Home
      Land
        Some
          More
            Stuff 0.34

これらの変数名を定義することに本当に慣れている場合は、いくつかの有用な解析アクションをpyparsingに追加すると、解析時に解析されたデータが再フォーマットされるため、後で直接処理できます。

wd = Word(alphas, alphanums)
number = Word(nums+'+-', nums+'.').setParseAction(lambda t:float(t[0]))
rvaluewd = wd.copy().setParseAction(lambda t: '"%s"' % t[0])
rvalue = rvaluewd | number | QuotedString('"')

defn = delimitedList(wd, '/')('key') + '=' + rvalue('value')

def joinNamesWithAllCaps(tokens):
    tokens["key"] = '_'.join(map(str.upper, tokens.key))
defn.setParseAction(joinNamesWithAllCaps)

for d in data:
    result = defn.parseString(d)
    print result.key,'=', result.value

プリント:

SAME_SAME2_FOOT_ANKLE_JOINT_ACTUATOR_SENSOR_TEMPERATURE_VALUE = 4.123
SAME_SAME2_BATTERY_NAME = "SomeString"
SAME_SAME2_HOME_LAND_SOME_MORE_STUFF = 0.34

(これにより、SomeString値も引用符で囲まれるため、結果の代入ステートメントは有効なPythonであることに注意してください。)

于 2011-07-25T00:39:34.657 に答える