【问题标题】:In Python, matching the first occurrence of a word AFTER the occurrence of another word在 Python 中,匹配一个单词的第一次出现在另一个单词出现之后
【发布时间】:2016-10-20 18:58:27
【问题描述】:

我正在尝试替换仅在 JSON 文本字符串中的另一个单词之后出现的单词。我一直在努力使用正则表达式来做到这一点,但只使用 Python 函数就可以了。

所以我想要的是找到"LEVEL1"的第一次出现:(带引号),然后找到"session_transition":的第一次出现,然后在"session_transition":之后找到引号中的任何字符串,然后用另一个替换它细绳。这是我正在使用的字符串:

"BASELINE": {
    "audio_volume": 150,
    "cry_threshold": 70,
    "cry_transition": "LEVEL1",
    "expected_volume": 63,
    "led_color": "BLUE",
    "led_blink_speed": "NONE",
    "motor_amplitude": 0.97,
    "motor_frequency": 0.5,
    "power_transition": "SUSPENDED",
    "seconds_to_ignore_cry": 10.0,
    "seconds_in_state": -1.0,
    "session_transition": "ONLINE",
    "track": "RoR",
    "timer_transition": null,
    "active_session" : 1
},
"LEVEL1": {
    "audio_volume": 300,
    "cry_threshold": 75,
    "expected_volume": 63,
    "cry_transition": "LEVEL2",
    "led_color": "PURPLE",
    "led_blink_speed": "NONE",
    "motor_amplitude": 0.76,
    "motor_frequency": 1.20,
    "power_transition": "SUSPENDED",
    "seconds_to_ignore_cry": 10.0,
    "seconds_in_state": 480.0,
    "session_transition": "ONLINE",
    "track": "RoR",
    "timer_transition": "BASELINE",
    "active_session" : 1
}

}

例如,下面我想在"LEVEL1": 下找到"ONLINE" 并将其替换为"session_transition": 到"OFFLINE",所以它看起来像这样:

"LEVEL1": {
    "audio_volume": 300,
    "cry_threshold": 75,
    "expected_volume": 63,
    "cry_transition": "LEVEL2",
    "led_color": "PURPLE",
    "led_blink_speed": "NONE",
    "motor_amplitude": 0.76,
    "motor_frequency": 1.20,
    "power_transition": "SUSPENDED",
    "seconds_to_ignore_cry": 10.0,
    "seconds_in_state": 480.0,
    "session_transition": "OFFLINE",
    "track": "RoR",
    "timer_transition": "BASELINE",
    "active_session" : 1
}

到目前为止,我有 r"(?<=\"LEVEL1\"\:).* 来匹配第一个匹配项,但不知道如何继续。

【问题讨论】:

  • 你为什么要尝试使用正则表达式?解析它并处理字典。
  • @jonrsharpe:如果你的意思是这样,我需要字符串保持字符串而不是字典。
  • 为什么?为什么以后不能把它变回字符串?您要解决的实际问题是什么?

标签: python regex


【解决方案1】:

我建议您使用 Python 中内置的 JSON 库。您可以轻松地将 JSON 转换为 Python Dict 对象。这也会阻止您使用复杂的正则表达式。最好降低可读性的复杂性。 文档: Python 3.4 Python 2.7

在 Python 2 中

import json
jsonDict = json.loads('["foo", {"bar":["baz", null, 1.0, 2]}]')
print(jsonDict)

结果:

['foo', {'bar': ['baz', None, 1.0, 2]}]

然后,您可以像处理 Python 字典一样轻松地进行操作。这样看起来更直观。

完成后,您可以使用转换它

jsonStr = json.dumps(jsonDict)
print(jsonStr)

结果:

["foo", {"bar":["baz", null, 1.0, 2]}]

【讨论】:

  • 这是一个很好的解决方案,而且很有效。但是,当我从 JSON 转换回字符串时,数据会重新排序。我知道这是意料之中的,但我不希望修改的字符串与其初始状态无序。
【解决方案2】:

好的,我可以通过以下方式解决这个问题:

#1)Find the unique string "LEVEL1": and save its index
after_index = configuration_in_text_format.index('"LEVEL1":')
#2)Starting from previous index, find the "session_transition": string and save its index
after_index = configuration_in_text_format.find('"session_transition":', after_index)
#3)Create a new string of bottom part with "session_transition": as first line
new_config_in_text_format = configuration_in_text_format[after_index:]
#4)Remove the first line with "session_transition": in it
new_config_in_text_format = new_config_in_text_format[new_config_in_text_format.find('\n')+1:]
#5)Create a new string to replace the deleted new line
new_line_str = '"session_transition": "OFFLINE",\n'
#6)Put new string on top of remaining text, effectively replacing old line
new_config_in_text_format = new_line_str + new_config_in_text_format
#7)Take the top part of original text and append the newly modified bottom part
new_config_in_text_format = configuration_in_text_format[:after_index] + new_config_in_text_format
print new_config_in_text_format

以及正确的输出:

  "BASELINE": {
    "audio_volume": 150,
    "cry_threshold": 70,
    "cry_transition": "LEVEL1",
    "expected_volume": 63,
    "led_color": "BLUE",
    "led_blink_speed": "NONE",
    "motor_amplitude": 0.97,
    "motor_frequency": 0.5,
    "power_transition": "SUSPENDED",
    "seconds_to_ignore_cry": 10.0,
    "seconds_in_state": -1.0,
    "session_transition": "ONLINE",
    "track": "RoR",
    "timer_transition": null,
    "active_session" : 1
},
"LEVEL1": {
    "audio_volume": 300,
    "cry_threshold": 75,
    "expected_volume": 63,
    "cry_transition": "LEVEL2",
    "led_color": "PURPLE",
    "led_blink_speed": "NONE",
    "motor_amplitude": 0.76,
    "motor_frequency": 1.20,
    "power_transition": "SUSPENDED",
    "seconds_to_ignore_cry": 10.0,
    "seconds_in_state": 480.0,
    "session_transition": "OFFLINE",
    "track": "RoR",
    "timer_transition": "BASELINE",
    "active_session" : 1
},

【讨论】:

    【解决方案3】:

    我认为你可以使用 string.index() 轻松做到这一点

    first_index = some_string.index('"Level1"')
    second_index = some_string[first_index:].index('"Online"')
    

    之后我让你来替换字符串。您应该可以使用some_string[second_index:].split('"') 完成此操作,然后使用拼接和连接将其重新组合在一起。

    【讨论】:

    • 我要替换的“ONLINE”不是我遇到的第一个;事实上,它可以是任何其他字符串,只要它在 LEVEL1-->session_transition 分支中。这就是为什么我要尝试匹配“LEVEL1”:首先匹配“session_transition”:下一个(按此顺序)。
    • 好的,所以换个词?重点是第一行你匹配你要匹配的单词,第二行匹配你要匹配的单词。
    • 谢谢,这让我找到了解决方案。我错误地陷入了正则表达式的无底深渊;经验教训。
    • 请注意,str.index 可以从 start 位置进行搜索,您不需要像这样对字符串进行切片来获取 second_index。
    • @bravosierra99 我投了赞成票,但它没有显示,因为我是这里的 n00b 并且需要更多的声誉。不过还是谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-03
    • 1970-01-01
    • 2021-05-09
    相关资源
    最近更新 更多