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

Replacing specific substrings in a specific part of a string

我有以下文本文件需要以某种方式进行编辑。 (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. (击球手 first_batsman) 与 (击球手 none_batsmen)

  2. (投球手 none_bowler) 与 (投球手 first_bowler)

  3. (裁判third_umpire)与(裁判leg_umpire)

  4. (旁观者no_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. 此代码还更改了 (goal: 部分中的“(batsmen first_batsmen)”部分,我不想要它。我只想要它更改 (init: 部分

  2. 目前对于 (init: 部分中的其他字符串,我必须用不同的语句重做此代码。例如:for '(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)。

对这些问题有什么想法吗?

谢谢

首先你需要找到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()

现在 match 中有 init 组。下一步是找到您要替换的术语,并实际替换它。 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'