开发者

Locating string literals in C++ source with regex, but not includes?

I want to introduce i18n in an existing application. As a first step, I need to replace the string literals with tr("something")开发者_C百科.

I have created the following regex to extract the strings:

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

However, this does not work. Without the negative lookbehind, it does match strings correctly, but also quoted includes which I want to avoid. I'm not quite familiar with negative lookbehinds, I just looked them up here.

Example:

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

How can I do this correctly?


Please try this one

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

It works directly(without groups). It also supports escaped quotes in strings. The only constraint here is one space between #include and file name. This is because QTcreator doesnt support quantifiers in negative lookbehind.

Ill try to fix it. But not sure that ill succeed.


You can use:

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

The strings in quotes are captured by the group.

In 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());


Ok, here is my solution (sort of):

First, I could not do it in Qt Creator, its regex capabilities seem to be not so good at the moment. So I used vim.

I opened all the affected files as vim buffers, then recorded the following macro:

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

This does the following:

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

The regex is vim-regex with \v that makes more natural (less escaping). In short, it uses a negative lookbehind as I originally wanted, with a slightly different syntax.

Now, I only had to run this macro for as many buffers I had open (in command mode):

78@a

The problem (and this is why it's only a "sort of" solution) is that whenever vim encounters a buffer where the regex fails (i.e. no string literals in the file) it stops repeating the macro. I couldn't find out how to fix that. Fortunately I had only a few files like that, so I could get away with manually re-running the above command to start repeating the macro again.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜