Нахождение строковых литералов в источнике C ++ с помощью регулярных выражений, но не включает? - PullRequest
1 голос
/ 25 июня 2011

Я хочу представить i18n в существующем приложении.В качестве первого шага мне нужно заменить строковые литералы на tr("something").

Я создал следующее регулярное выражение для извлечения строк:

(?<!#include)"([^"\\]|\\.)*"

Однако это не работает.Без негативного взгляда он правильно сопоставляет строки, но также включает в себя кавычки, которых я хочу избежать.Я не совсем знаком с негативными взглядами, я просто посмотрел их здесь .

Пример:

#include "hello.h"                           // should NOT match "\"hello.h\""
printf("Hello");                             // should match "\"Hello\""
cout << "hello" << "hello" << "hello";       // should match each three "\"hello\""'s

Как я могу сделать это правильно?

Ответы [ 3 ]

1 голос
/ 26 июня 2011

Пожалуйста, попробуйте это

(?<!#include\s)"(?:\\\"|[^"\n])*?"

Работает напрямую (без групп). Он также поддерживает экранированные кавычки в строках. Единственным ограничением здесь является один пробел между #include и именем файла . Это потому, что QTcreator не поддерживает квантификаторы в негативном виде.

Я попытаюсь это исправить. Но не уверен, что у меня все получится.

0 голосов
/ 27 июня 2011

Хорошо, вот мое решение (вроде):

Во-первых, я не смог сделать это в Qt Creator, его возможности регулярных выражений в данный момент кажутся не очень хорошими. Так что я использовал vim.

Я открыл все затронутые файлы как буферы vim, затем записал следующий макрос:

qa:%s/\v(#include\s+)@<!"([^"]*)"/tr(\0)/g<CR>:bn<CR>q

Это делает следующее:

qa                                       // start recording into register "a"
%s/\v(#include\s+)@<!"([^"]*)"/tr(\0)/g  // search and replace as specified
<CR>                                     // (hit enter)
:bn                                      // jump to the next buffer
<CR>                                     // (hit enter)
q                                        // end recording macro

Регулярное выражение - это vim-regex с \ v, что делает его более естественным (меньше экранирующего). Короче говоря, он использует отрицательный внешний вид, как я изначально хотел, с немного другим синтаксисом.

Теперь мне нужно было запустить этот макрос только для того количества буферов, которые у меня были открыты (в командном режиме):

78@a

Проблема (и именно поэтому это всего лишь «своего рода» решение) заключается в том, что всякий раз, когда vim встречает буфер, в котором происходит сбой регулярного выражения (т. Е. В файле нет строковых литералов), он прекращает повторять макрос. Я не мог найти, как это исправить. К счастью, у меня было всего несколько таких файлов, поэтому я смог вручную запустить команду, описанную выше, чтобы снова повторить макрос.

0 голосов
/ 25 июня 2011

Вы можете использовать:

(?!^#include).*?(\"[^\"]+?\").*?

Строки в кавычках фиксируются группой.

В Java:

    String s = "(?!^#include).*?(\"[^\"]+?\").*?";
    Pattern p = Pattern.compile(s);

    System.out.println(p.matcher("#include \"hello.h\" ").matches());
    System.out.println(p.matcher("printf(\"Hello\"); ").matches());
    System.out.println(p.matcher("cout << \"hello\" << \"hello\" << \"hello\"; ").matches());
...