检查变量子字符串是否在字符串中

时间:2019-05-20 08:14:05

标签: python string

我收到一个输入字符串,该字符串具有以两种可能的格式表示的值。例如:

#short format
data = '"interval":19'

>>> "interval":19


#extended format
data = '"interval":{"t0":19,"tf":19}'

>>> "interval":{"t0":19,"tf":19}

我想检查是否使用了短格式,以防万一,将其扩展。

考虑到字符串可以由多个值组成,即

data = '"interval":19,"interval2":{"t0":10,"tf":15}'

>>> "interval":19,"interval2":{"t0":10,"tf":15}

我不能只说:

if ":{" not in data:
    #then short format is used

我想编写如下代码:

if ":$(a general int/float/double number)" in data:
    #extract the number
    #replace ":{number}" with the extended format

我知道如何编写替换部分的代码。 我需要实现if条件的帮助:在我看来,我将其建模为变量子字符串,其中变量部分是其中的数字,而刚性格式是$(值名称)+“:”部分。

  "some_value":19
       ^       ^
 rigid format  variable part

编辑-为什么不解析它?

我知道字符串是“ JSON友好的”,我可以将其转换为字典,然后轻松地访问值。

确实,我的代码中已经有此解决方案。但是我不喜欢它,因为输入字符串可能是多级的,并且我需要独立于词典级别对生成的词典的叶值进行迭代。后者不是一件容易的事。

所以我想知道是否存在一种直接作用于字符串的方法。

2 个答案:

答案 0 :(得分:2)

如果替换t0tf以外的所有键,然后加上数字,则应该可以。
我为您展示了一个有关多级字符串的示例,该示例可能具有更好的形状:

import re

s = '"interval": 19,"t0interval2":{"t0":10,"tf":15},{"deeper": {"other_interval":23}}'

gex = '("(?!(t0|tf)")\w+":)\s*(\d+)'
new_s = re.sub(gex, r'\1 {"t0": \3, "tf": \3}', s)
print(new_s)
>>> print(new_s)
"interval": {"t0": 19, "tf": 19},"t0interval2":{"t0":10,"tf":15},{"deeper": {"other_interval": {"t0": 23, "tf": 23}}}

答案 1 :(得分:1)

您可以使用正则表达式。 ("interval":)(\d+)将查找字符串'"interval":',后跟任意数字。

让我们测试一下

data = '"interval":19,"interval2":{"t0":10,"tf":15},"interval":25'
result = re.sub(r'("interval":)(\d+)', r'xxx', data)
print(result)
# -> xxx,"interval2":{"t0":10,"tf":15},xxx

我们看到我们找到了正确的地方。现在,我们将创建您的目标格式。匹配的组在这里派上用场。在正则表达式("interval":)中是组1,(\d+)是组2。

现在,我们使用这些组的内容来创建您想要的结果。

data = '"interval":19,"interval2":{"t0":10,"tf":15},"interval":25'
result = re.sub(r'("interval":)(\d+)', r'\1{"t0":\2,"tf":\2}', data)
print(result)
# -> "interval":{"t0":19,"tf":19},"interval2":{"t0":10,"tf":15},"interval":{"t0":25,"tf":25}

如果涉及浮点值,则必须将(\d+)更改为([.\d]+)

如果不仅需要interval,而且还需要任何Unicode标准单词字符,则可以使用特殊序列\w,并且由于它可能是多个字符,因此表达式将为\w+

data = '"interval":19,"interval2":{"t0":10,"tf":15},"Monty":25.4'
result = re.sub(r'("\w+":)([.\d]+)', r'\1{"t0":\2,"tf":\2}', data)
print(result)
# -> "interval":{"t0":19,"tf":19},"interval2":{"t0":{"t0":10,"tf":10},"tf":{"t0":15,"tf":15}},"Monty":{"t0":25.4,"tf":25.4}

当!是的,我们找到了"Monty",但是现在也找到了第二部分的值。我们必须以某种方式解决此问题。让我们来看看。我们不希望("\w+")前面有{,因此将在断言后使用负向查找(?<!{)("\w+")。在数字部分(\d+)之后,我们不需要}或其他数字,因此我们在这里使用负超前断言([.\d]+)(?!})(?!\d)。 / p>

data = '"interval":19,"interval2":{"t0":10,"tf":15},"Monty":25.4'
result = re.sub(r'(?<!{)("\w+":)([.\d]+)(?!})(?!\d)', r'\1{"t0":\2,"tf":\2}', data)
print(result)
# -> "interval":{"t0":19,"tf":19},"interval2":{"t0":10,"tf":15},"Monty":{"t0":25.4,"tf":25.4}

万岁,行得通!

正则表达式功能强大且有趣,但是如果您开始添加更多约束,则可能变得难以管理。