0

I am trying to construct a regular expression to find the text of the following variations.

NSLocalizedString(@"TEXT")
NSLocalizedStringFromTable(@"TEXT")
NSLocalizedStringWithDefaultValue(@"TEXT")
...

The goal is to extract TEXT. I have been able to construct a regex for each individual function or macro, e.g., (?<=NSLocalizedString)\(@"(.*?)". However, I am looking for a solution that does the job no matter what the name of the function as long as it starts with NSLocalizedString.

I assumed it was as simple as (?<=NSLocalizedString\w+)\(@"(.*?)", but that does't seem to do the trick.

Bart Jacobs
  • 9,022
  • 7
  • 47
  • 88
  • 1
    Don't bother with assertions. Just use your regex this way - `NSLocalizedString\w+\(@"(.*?)"` and read the result in capture group 1. –  Nov 16 '13 at 18:59

2 Answers2

4

How about this one?

/NSLocalizedString\w*\(@"(.*)"\)/

Explanation:

  NSLocalizedString        'NSLocalizedString'
  \w+                      word characters (a-z, A-Z, 0-9, _) (0 or
                           more times (matching the most amount
                           possible))
  \(                       '('
  @"                       '@"'
  (                        group and capture to \1:
    .*                       any character except \n (0 or more times
                             (matching the most amount possible))
  )                        end of \1
  "                        '"'
  \)                       ')'
Gergo Erdosi
  • 40,904
  • 21
  • 118
  • 94
1

The only reason your regex doesn't work is because the regex engine doesn't support variable length lookbehinds. The (?<=NSLocalizedString\w+) is variable length so can't be used.

Firstly it needs to be \w* not \w+, to allow your first example string to match.

If you move the \w* outside the lookbehind (?<=NSLocalizedString)\w* it will work just fine.

Alternatively, since you have to use a capturing group to grab the text value anyway, theres no need for the lookbehind at all. Change the (?<= to a (?: and it becomes a non-capturing group (which can be variable length), and then just grab your text value from group 1.

Your attempt was:

(?<=NSLocalizedString\w+)\(@"(.*?)"

Both of these minor changes should make it work:

(?<=NSLocalizedString)\w*\(@"(.*?)"

(?:NSLocalizedString\w*)\(@"(.*?)"

The following is actually not supported in Objective-C:

The solution that will extract exactly TEXT without using any groups is:

NSLocalizedString\w*\(@"\K[^"]*

It avoids the need to use a negative lookbehind (which can't be used for reasons I explain below) by using the \K modifier, which chops off anything before it from the match.

OGHaza
  • 4,795
  • 7
  • 23
  • 29
  • just updated to include what I think will be your ideal solution (matches exactly `TEXT` without using any groups - as you were originally trying to do) – OGHaza Nov 16 '13 at 18:58
  • Your solution is indeed ideal, but the `\K` modifier is not supported in Objective-C (http://stackoverflow.com/questions/13542950/support-of-k-in-regex). The alternatives you suggested do indeed work. The gotcha was indeed that lookbehind/lookahead assertions cannot have a variable length as you pointed out. – Bart Jacobs Nov 16 '13 at 20:53