Замена указанных c подстрок в указанной c части строки - PullRequest
1 голос
/ 26 марта 2020

У меня есть следующий текстовый файл, который нужно отредактировать определенным образом. Часть файла, которая находится внутри (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)
)
)
)

In этот файл я хочу заменить каждой строкой, которая находится внутри (init: раздел на требуемую строку. В этом случае я хочу заменить:

  1. (batsmen first_batsman с *

  2. (зритель 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()

Термин Предикат_batsmen здесь содержит слово нет . Так работает нормально. Этот код удовлетворяет только пункту 1. упомянутый выше

У меня есть три проблемы.

  1. Этот код также изменяет часть '(batsmen first_batsmen)' в * 1 043 * (цель: часть, которую я не хочу. Я только хочу изменить (init: part

  2. В настоящее время для других строк в (init: part, мне нужно переделайте этот код с другим оператором. Например: for '(bowler none_bowler)', то есть пункт номер 2 выше, я должен снова получить копию закодированных строк, что, на мой взгляд, не очень хорошая техника кодирования. Есть лучший способ для этого .

  3. Если мы рассмотрим первую строку в (init: , которая должна быть перезаписана, т.е. (batsmen first_batsman). Есть ли способ в python, что нет независимо от того, что написано в вопросительном знаке, часть строки вроде (batsmen ?????? _ batsman) можно заменить на none . На данный момент это 'first' но даже если написано 'second' ((batsmen second_batsman)) или 'last' ((batsmen last_batsman)), я хочу заменить его на 'none' (batsmen none_batsman).

Есть идеи по этим вопросам?

Спасибо

1 Ответ

1 голос
/ 26 марта 2020

Прежде всего вам нужно найти init -группу. init -группа, похоже, имеет структуру:

(:init
    ...
)

, где ... - это некоторое повторение текста, содержащегося в скобках, например, "(batsmen first_batsman)". Регулярные выражения - это мощный способ найти такие шаблоны в тексте. Если вы не знакомы с регулярными выражениями (или для краткости регулярное выражение), посмотрите здесь .

Следующее регулярное выражение находит эту группу:

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' et c.

...