1

I couldn't find anything that specifically addressed how to find square brackets in predicates on Stack Overflow or on Google so I thought I would post it here and see if anyone can explain the solution.

NSString *mstr = @"fasd[981db7007771ffa3]dfaads";
NSString *test =@".*\\[[0-9,a-f]{16}\\].*";
//NSPredicate *pred = [NSPredicate predicateWithFormat:@"SELF MATCHES '.*\\\\[[0-9,a-f]{16}\\\\].*'"]; //works
NSPredicate *pred = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", test];
if ([pred evaluateWithObject:mstr]) {
    NSLog(@"Yes");
}

It seems that when escaping the brackets in-line you need four backslashes but if you put it in a string you only need two. Not clear why that is the case.

Ben
  • 51,770
  • 36
  • 127
  • 149
KWorkman
  • 41
  • 4

1 Answers1

2

The reason is because NSPredicate does it's own backslash escaping, along with the C-compiler's. So, let's walk through the steps that are done first:

Source:

NSPredicate *pred = [NSPredicate predicateWithFormat:@"\\\\[(regex here)\\\\]"];

C-precompiler: (unescapes one set of backslashes)

NSPredicate *pred = [NSPredicate predicateWithFormat:@"\\[(regex here)\\]"];

NSPredicate internal compiler: (unescapes the second set of backlashes, and compiles the regex).

NSPredicate *pred = [NSPredicate predicateWithFormat:@"\[(regex here)\]"];

When passing in a string literal, it is compiled by NSPredicate first, whereas when passing a variable, it isn't compiled in the same way (it skips the escaping part).

Richard J. Ross III
  • 55,009
  • 24
  • 135
  • 201