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.
精彩评论