Регулярное выражение для замены логического выражения на bool - PullRequest
8 голосов
/ 29 августа 2008

Я работаю над базой кода C ++, которая была недавно перемещена из X / Motif в Qt. Я пытаюсь написать сценарий Perl, который заменит все вхождения Boolean (из X) в bool. Скрипт просто делает простую замену.

s/\bBoolean\b/bool/g

Есть несколько условий.

1) В нашем коде есть CORBA, и \ b соответствует CORBA :: Boolean, который должен быть не .
2) Он не должен совпадать, если он был найден в виде строки (то есть "Boolean")

Изменено:

Для # 1 я использовал lookbehind

s/(?<!:)\bBoolean\b/bool/g;

Для # 2 я использовал lookahead.

<code>s/(?<!:)\bBoolean\b(?!")/bool/g

Это, скорее всего, будет работать для моей ситуации, но как насчет следующих улучшений?

3) Не совпадать, если в середине строки (спасибо nohat ).
4) Не совпадать, если в комментарии. (// или / ** /)

Ответы [ 9 ]

3 голосов
/ 30 августа 2008

s / [^:] (?! ") \ BBoolean \ б / BOOL / г

Это не соответствует строкам, где Boolean находится в начале строки, потому что [^:] это "соответствует символу, который не является:".

2 голосов
/ 30 августа 2008

Остерегайтесь с этим проверочным утверждением. Это будет соответствовать, только если Boolean - последняя часть строки, но не в середине строки. Вам нужно будет сопоставить четное число кавычек, предшествующих совпадению, если вы хотите быть уверенными, что вы не в строке (при условии, что нет многострочных строк и нет экранированных встроенных кавычек).

1 голос
/ 18 сентября 2008
#define Boolean bool

Пусть об этом позаботится препроцессор. Каждый раз, когда вы видите логическое значение, вы можете либо исправить его вручную, либо надеяться, что регулярное выражение не сделает ошибку. В зависимости от того, сколько макросов вы используете, вы можете выбросить из cpp.

1 голос
/ 30 августа 2008
s/[^:]\bBoolean\b[^"]/bool/g

Редактировать: Крысы, снова избили. +1 за избиение меня, сэр.

0 голосов
/ 18 сентября 2008

Часть "'Boolean' в середине строки" звучит немного неправдоподобно, сначала я бы проверил, есть ли это в коде с чем-то вроде

m/"[^"]*Boolean[^"]*"/

А если их нет или несколько, просто проигнорируйте этот случай.

0 голосов
/ 17 сентября 2008
  1. ...
  2. ...
  3. Не совпадать, если в середине строки (спасибо, ничего).
  4. Не совпадать, если в комментарии. (// или / ** /)

Нет, можно сделать с простым регулярным выражением. Для этого вам нужно на самом деле посмотреть каждый символ слева направо и решить, что это за вещь, по крайней мере, достаточно хорошо, чтобы отличать комментарии от многострочных комментариев от строк от других вещей. и затем вам нужно проверить, содержит ли часть «прочее» то, что вы хотите изменить.

Итак, я не знаю точных синтаксических правил для комментариев и строк в C ++, поэтому следующее будет неточным и полностью отлаженным, но оно даст вам представление о сложности, которую вы против.

my $line_comment      = qr! (?> // .* \n? ) !x;
my $multiline_comment = qr! (?> /\* [^*]* (?: \* (?: [^/*] [^*]* )? )* )* \*/ ) !x;
my $string            = qr! (?> " [^"\\]* (?: \\ . [^"\\]* )* " ) !x;
my $boolean_type      = qr! (?<!:) \b Boolean \b !x;

$code =~ s{ \G (
      $line_comment
    | $multiline_comment
    | $string
    | ( $boolean_type )
    | .
) }{
    defined $2 ? 'bool' : $1
}gex;

Пожалуйста, не просите меня объяснить это во всех его тонкостях, это займет у меня один день и другой. Просто купите и прочитайте Джеффа Фридла Освоение регулярных выражений , если вы хотите точно понять, что здесь происходит.

0 голосов
/ 17 сентября 2008

Чтобы не писать полноценный C-парсер на perl, вы пытаетесь найти баланс. В зависимости от того, сколько нужно изменить, я склонен сделать что-то вроде очень ограничительного s ///, а затем все, что все еще соответствует / Boolean /, будет записано в файл исключений для принятия человеком решения. Таким образом, вы не пытаетесь проанализировать средние строки C, многострочный комментарий, условно скомпилированный текст и т. Д., Которые могут присутствовать.

0 голосов
/ 04 сентября 2008

3) Не совпадать, если в середине строки (спасибо, ничего).

Вы можете написать reg ex для проверки ". * Boolean. *". Но что, если внутри строки есть кавычка (")? Итак, у вас есть больше работы, чтобы не исключать (\") шаблон.

4) Не совпадать, если в комментарии. (// или / * * /)

Для '//' вы можете иметь регулярное выражение для исключения //.* Но лучше было бы сначала добавить регулярное выражение для сравнения всей строки для // комментариев ((. *) (//.* )), а затем примените замену только к 1 доллару (первый соответствующий шаблон).

Для / * * / это более сложно, так как это многострочный шаблон. Один из подходов может состоять в том, чтобы сначала выполнить весь ваш код, чтобы он соответствовал многострочным комментариям, а затем удалить только те части, которые не соответствуют ... что-то вроде ... (. *) (/*.**/) (. *). Но фактическое регулярное выражение будет еще более сложным, поскольку у вас будет не один, а несколько многострочных комментариев.

Теперь, что если у вас есть / * или * / внутри // блока? (Я не знаю, зачем вам это нужно ... но закон Мерфи гласит, что вы можете иметь это). Очевидно, что есть какой-то выход, но моя идея состоит в том, чтобы подчеркнуть, насколько плохим будет регулярное выражение.

Мое предложение здесь состоит в том, чтобы использовать некоторый лексический инструмент для C ++ и заменить токен Boolean на bool. Ваши мысли?

0 голосов
/ 30 августа 2008

Чтобы исправить условие 1 попробуйте:

s/[^:]\bBoolean\b(?!")/bool/g

[^:] говорит, что соответствует любому символу, кроме ":".

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