在字符串的特定部分替换特定的子字符串

时间:2020-03-26 16:40:40

标签: python regex str-replace

我有一个以下文本文件,将以某种方式进行编辑。文件中位于(init:部分)内部的部分将被覆盖,除了应编辑的部分外,其他所有内容都不能编辑。

文件:

(define (problem bin-picking-doosra)

(:domain bin-picking-second)
;(:requirements :typing :negative-preconditions)
(:objects        
)
(:init 
        (batsmen first_batsman)
        (bowler none_bowler)
        (umpire third_umpire)
        (spectator no_spectator)
)

(:goal (and
                (batsmen first_batsman)
                (bowler last_bowler)
                (umpire third_umpire)
                (spectator full_spectator)
)
)
)

在此文件中,我想用必需的字符串替换(init:部分”中的每一行。在这种情况下,我想替换:

  1. (batsmen first_batsman)与(batsmen none_batsmen)

  2. (保龄球none_bowler)和(保龄球first_bowler)

  3. (裁判第三人)和(裁判leg_umpire)

  4. (spectator no_spectator)与(spectator empty_spectator)

我当前拥有以下代码:

file_path = "/home/mus/problem_turtlebot.pddl"
s = open(file_path).read()
s = s.replace('(batsmen first_batsman)', '(batsmen '+ predicate_batsmen + '_batsman)')
f = open(file_path, 'w')
f.write(s)
f.close()

此处的 predicate_batsmen 一词包含 none 一词。这样可以很好地工作。该代码仅满足上述第1点。

我有三个问题。

  1. 此代码还更改了我不想要的(目标:部分中的(batsmen first_batsmen)'部分。我只希望它更改(init:部分

  2. 当前,对于(init:部分中的其他字符串,我必须使用不同的语句重做此代码。例如:对于'(bowler none_bowler)',即上述第2点,我必须再次获得编码行的副本,我认为这不是一种好的编码技术,任何更好的方法。

  3. 如果我们认为(init:)中的第一个字符串将被覆盖,即(batsmen first_batsman)。python中是否有一种方法,无论用什么方式写像(batsmen ?????? _ batsman)这样的字符串中的问号部分可以用 none 代替。现在,它是'first',即使已写'second'((batsmen second_batsman))或'last'((batsmen last_batsman)),我想将其替换为'none' (击球手none_batsman)。

关于这些问题有什么想法吗?

谢谢

1 个答案:

答案 0 :(得分:1)

首先,您需要找到init组。 init组似乎具有以下结构:

(:init
    ...
)

其中...是括号内包含的文本的重复出现,例如"(batsmen first_batsman)"。正则表达式是在文本中定位此类模式的有效方法。如果您不熟悉正则表达式(或简称regex),请看看here

以下正则表达式可找到该组:

import re

#Matches the items in the init-group:
item_regex = r"\([\w ]+\)\s+"
#Matches the init-group including items:
init_group_regex = re.compile(r"(\(:init\s+({})+\))".format(item_regex)) 

init_group = init_group_regex.search(s).group()

现在,您在init中拥有match组。下一步是找到要替换的术语,然后实际替换它。 re.sub可以做到!首先将映射存储在字典中:

mappings = {'batsmen first_batsman': 'batsmen '+ predicate_batsmen + '_batsman',
'bowler none_bowler': 'bowler first_bowler',
'umpire third_umpire': 'umpire leg_umpire',
'spectator no_spectator': 'spectator empty_spectator'}

查找事件并用它们对应的值一个一替换:

for key, val in mappings.items():
    init_group = re.sub(key, val, init_group)

最后,您可以替换原始字符串中的init组:

s = init_group_regex.sub(init_group, s)

这真的很灵活!您可以在mappings中使用正则表达式使其与您喜欢的任何内容匹配,包括:

mappings = {'batsmen \w+_batsman': '(batsmen '+ predicate_batsmen + '_batsman)'}

匹配'batsmen none_batsman''batsmen first_batsman'