Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/python-2.7/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
从Python中的字符串和模板获取关键字值_Python_Python 2.7 - Fatal编程技术网

从Python中的字符串和模板获取关键字值

从Python中的字符串和模板获取关键字值,python,python-2.7,Python,Python 2.7,最后,我得到了@jornsharpe示例的解决方案,我在这里展示了它。它适用于我,只是我需要使用os.path.split分割文件夹和文件名,以确保模板中关键字的唯一性 def parse_kwdict(s, template, keys, kwmark='$'): kw2rekw = {key:'(?P<'+key+'>.*)' for key in keys} pattern = replace(template, kw2rekw, kwmark=kwmark)

最后,我得到了@jornsharpe示例的解决方案,我在这里展示了它。它适用于我,只是我需要使用os.path.split分割文件夹和文件名,以确保模板中关键字的唯一性

def parse_kwdict(s, template, keys, kwmark='$'):
    kw2rekw = {key:'(?P<'+key+'>.*)' for key in keys}
    pattern = replace(template, kw2rekw, kwmark=kwmark)
    return re.match(pattern, s).groupdict()

def replace(template, kwdict, kwmark='$'):
    name = template
    for key, val in kwdict.iteritems():
        if val is not None:
            name = name.replace(kwmark+key, str(val))
    return name
这样我就可以从字符串和模板中提取键的值

比如说,

template = '/parent/folder/$sensor/$year.$day/$freq/$sensor.$location.$year.$day.dat'
keys = ['year', 'day', 'location', 'sensor', 'freq'] # keywords in the template
s = '/parent/folder/SensorA/2011.123/5Hz/SensorA.E.2011.123.dat'
kwdict = parse_kwdict(s, template, keys)
产生

kwdict = {'year':2011, 'day':123, 'location':'E', 'sensor':'SensorA', 'freq':'5Hz'}
我的案子需要处理的一些笔记

  • 关键字的值中没有空格

  • 模板中的关键字之间总是有一些分隔符,如字母、点、下划线、斜杠等

  • 模板中的关键字列在
    键中(关键字=“$”+键),它们完全不同。不会有像
    $freq
    $frequency
    这样的关键词会让人感到模糊

  • 关键字仅包含字母,不包含特殊字符

  • 关键字的值包括字母和数字,没有特殊字符,但也可以是“”

  • 关键字可以在模板和字符串中出现一次或多次,也可以不出现。如果关键字出现多次,则字符串中的值相同

  • 短篇故事:您不能(在一般情况下)可靠地反转合并,您的第一个示例是明确的:
    template='T$a$b\u an\u$c'
    string='这是一个示例'
    可以给出
    a='b='his'
    a='h'b='is'
    a='hi b='s'
    ,等等

    长话短说:

    • 首先需要解析模板以识别固定部分和可替换令牌:可替换令牌是
      $
      ,后跟一个小写字符,范围为
      a-z
      ,其余的都是固定的
    • 然后您需要转义固定部分中的所有特殊字符(至少
      ?(){}\:
      可能还有其他字符)
    • 然后,通过将模板中的可替换标记替换为
      *
      ,并将固定部分替换为其转义值来构建正则表达式
    • 如果字符串与正则表达式匹配,则应该给出一个可能的映射(可能还有其他映射)小心:可能还有其他可能性
    您可以尝试使用ungreedy匹配(
    *?
    而不是
    *
    )。如果你得到了与贪婪搜索完全相同的解决方案,那么这个解决方案应该是唯一的——更确切地说,我不确定这一点,但无法想象一个例子会是错误的

    上次编辑的最后备注:

    • 如果关键字不是单个字母,您必须指定如何识别它们(shell设计人员设想的
      ${xxz}
      不仅仅是偶然的)
    • 模板
      '/AAA/$a.$b.$c.txt'
      不会使用上述方法给出唯一的结果:
      /AAA/x.y.z.t.txt
      可以给出
      {'a':'x.y','b':'z','c':'t'}
      (gready),或
      {'a':'x','b':'y','c':'z.t'}
      (ungreedy)

      • 以下是您可以采取的方法的一般示例;我不完全清楚需要多少调整才能满足您的需求。基本上,它是从基于
        $
        的模板字符串转换为带有命名捕获组的正则表达式模式,然后使用该模式从实际路径提取数据:

        >>> import re
        
        >>> template = '/parent/folder/$freq/$name.dat'  # base template
        >>> parts = {
            'freq': r'(?P<freq>\d+Hz)',  # one or more digits then Hz
            'name': r'(?P<name>[a-z]{3,8})',  # three to eight lowercase letters
        }  # patterns for the parts of the template
        
        >>> pattern = re.sub(
            r'\$([^/.]+)',  # dollar followed by characters excluding / and .
            lambda match: parts[match.group(1)], 
            template
        )  # re.sub creates the pattern to match the actual path
        >>> pattern
        '/parent/folder/(?P<freq>\\d+Hz)/(?P<name>[a-z]{3,8}).dat'
        
        >>> re.match(
            pattern,     
            '/parent/folder/5Hz/hello.dat'
        ).groupdict()  # re.match extracts the appropriate data
        {'freq': '5Hz', 'name': 'hello'}
        
        >>重新导入
        >>>template='/parent/folder/$freq/$name.dat'#基本模板
        >>>零件={
        “频率”:r'(?P\d+Hz)#一个或多个数字,然后是Hz
        'name':r'(?P[a-z]{3,8}),#三到八个小写字母
        }#模板各部分的图案
        >>>模式=re.sub(
        r“\$([^/]+)”,#美元后跟不包括/和的字符。
        lambda匹配:零件[匹配组(1)],
        模板
        )#re.sub创建模式以匹配实际路径
        >>>图案
        “/parent/folder/(?P\\d+Hz)/(?P[a-z]{3,8}).dat”
        >>>复赛(
        图案
        “/parent/folder/5Hz/hello.dat”
        ).groupdict()#re.match提取适当的数据
        {'freq':'5Hz','name':'hello'}
        

        请注意,字典键必须是唯一的,因此,如果模板中出现两次(
        $year
        ),则您必须想出一些方法来区分这两个值。

        您实际上想要实现什么?为什么不使用常规的
        repr
        格式,您可以使用
        ast.literal\u eval
        轻松解析该格式?@jornsharpe我想我的第一个关于从模板进行正向替换的说明让您感到困惑。我需要的是,当我有一个字符串、一个模板和模板中的关键字列表时,如何从字符串中获取关键字的值?同样,目的是什么?您尝试过什么,到底有什么问题?@Dr.Lee您希望如何可靠地逆转它?以扩展字符串“his”为例-是重新模板化的版本“$bis”还是“$a”?根据给定的条件,可能有很多答案。假设
        s='这是一个示例。
        template='T$a$b'an'c'
        ,而
        kwdict的键是
        ['a','b','c']
        ,答案可以是
        {'a':'his','b':'is','c':'example.}
        正如你提到的,答案是
        {'a':'h','b':'is','c':'example.}
        也是正确的thx@SergeBallesta我更新了我的问题,去掉了一些模糊之处。
        >>> import re
        
        >>> template = '/parent/folder/$freq/$name.dat'  # base template
        >>> parts = {
            'freq': r'(?P<freq>\d+Hz)',  # one or more digits then Hz
            'name': r'(?P<name>[a-z]{3,8})',  # three to eight lowercase letters
        }  # patterns for the parts of the template
        
        >>> pattern = re.sub(
            r'\$([^/.]+)',  # dollar followed by characters excluding / and .
            lambda match: parts[match.group(1)], 
            template
        )  # re.sub creates the pattern to match the actual path
        >>> pattern
        '/parent/folder/(?P<freq>\\d+Hz)/(?P<name>[a-z]{3,8}).dat'
        
        >>> re.match(
            pattern,     
            '/parent/folder/5Hz/hello.dat'
        ).groupdict()  # re.match extracts the appropriate data
        {'freq': '5Hz', 'name': 'hello'}