Есть ли в Python регулярное выражение, которое может изменить все "foo" на "bar" в строках, начинающихся с "#"? - PullRequest
2 голосов
/ 10 февраля 2009

Можно ли написать одно регулярное выражение Python, которое можно применить к многострочной строке, и заменить все вхождения «foo» на «bar», но только в строках, начинающихся с «#»?

Мне удалось заставить это работать в Perl, используя символ регулярного выражения Perl \ G, который соответствует концу предыдущего соответствия. Тем не менее, Python не поддерживает это.

Вот решение Perl, если оно помогает:

my $x =<<EOF;
# foo
foo
# foo foo
EOF

$x =~ s{
        (            # begin capture
          (?:\G|^\#) # last match or start of string plus hash
          .*?        # followed by anything, non-greedily
        )            # end capture
        foo
      }
      {$1bar}xmg;

print $x;

Правильный вывод, конечно, таков:

# bar
foo
# bar bar

Можно ли это сделать в Python?


Редактировать: Да, я знаю, что можно разбить строку на отдельные строки и проверить каждую строку, а затем решить, применять ли преобразование, но, пожалуйста, поверьте мне, что в этом случае это будет нетривиально. Мне действительно нужно сделать это с помощью одного регулярного выражения.

Ответы [ 3 ]

3 голосов
/ 10 февраля 2009
lines = mystring.split('\n')
for line in lines:
    if line.startswith('#'):
        line = line.replace('foo', 'bar')

Нет необходимости в регулярном выражении.

1 голос
/ 10 февраля 2009

Это выглядит довольно легко сделать с помощью регулярного выражения:

>>> import re
... text = """line 1
... line 2
... Barney Rubble Cutherbert Dribble and foo
... line 4
... # Flobalob, bing, bong, foo and brian
... line 6"""
>>> regexp = re.compile('^(#.+)foo', re.MULTILINE)
>>> print re.sub(regexp, '\g<1>bar', text)
line 1
line 2
Barney Rubble Cutherbert Dribble and foo
line 4
# Flobalob, bing, bong, bar and brian
line 6

Но тогда пробовать ваш пример текста не так хорошо:

>>> text = """# foo
... foo
... # foo foo"""
>>> regexp = re.compile('^(#.+)foo', re.MULTILINE)
>>> print re.sub(regexp, '\g<1>bar', text)
# bar
foo
# foo bar

Итак, попробуйте это:

>>> regexp = re.compile('(^#|\g.+)foo', re.MULTILINE)
>>> print re.sub(regexp, '\g<1>bar', text)
# foo
foo
# foo foo

Это , похоже, работает, но я не могу найти \ g в документации 1015 *!

Мораль: не пытайтесь кодировать после пары пива.

0 голосов
/ 10 февраля 2009

\ g работает в Python точно так же, как Perl, и в документации .

"В дополнение к escape-символам и обратным ссылкам, как описано выше, \ g будет использовать подстроку, соответствующую имени группы, как определено синтаксисом (? P ...). \ G использует соответствующий номер группы; \ Следовательно, g <2> эквивалентно \ 2, но не является неоднозначным в замене, такой как \ g <2> 0. \ 20 будет интерпретироваться как ссылка на группу 20, а не ссылка на группу 2, за которой следует литерал символ '0'. Обратная ссылка \ g <0> заменяет всю подстроку, совпадающую с RE. "

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...