1

I've got the following snippet:

$file = '/mnt/stoneshare/cache/video/10_12_101_38/000/011/M00001.mp4';

preg_match('/[\/\\](\d+_\d+_\d+_\d+)[\/\\]/', $file, $matches);

var_dump($matches);

Which, apparently, produces:

preg_match(): Compilation failed: missing terminating ] for character class at offset 27

Yet, when I run the same example in an online test tool, it works.

What is the problem here?

tomsseisums
  • 13,168
  • 19
  • 83
  • 145

3 Answers3

3

Just add an escape:

preg_match('/[\/\\\](\d+_\d+_\d+_\d+)[\/\\\]/', $file, $matches);
//       here __^       and           __^
Toto
  • 89,455
  • 62
  • 89
  • 125
  • Yes, works! But, why so? It looks incorrect - as if I'd escape backslash and then also escape bracket, and my IDE screws up syntax highlighting this way. And yes, the online tool errors out on this one. – tomsseisums Apr 04 '14 at 09:03
  • @jolt: I don't know the real reason of this behaviour. It's different in other language as perl for example where `[\/\\\]` is an erreur. – Toto Apr 04 '14 at 09:08
  • @jolt `var_dump($pattern);` your original regex: `/[\/\]...` the regex parser needs a properly escaped backslash. Also see my [related question](http://stackoverflow.com/questions/20818283/how-to-properly-escape-a-backslash-to-match-a-literal-backslash-in-single-quoted), if you need more input :) – Jonny 5 Apr 04 '14 at 10:15
1

You need to add one more backslash in your pattern.

preg_match('/[\/\\\](\d+_\d+_\d+_\d+)[\/\\\]/', $file, $matches);

Because the backslash is itself a special character, you need to escape it with another backslash ( \ ) if you want to include it literally in an expression. What ’ s more, because a backslash followed by another character within a string is itself seen as an escaped character in PHP, you usually need to add a third backslash ( \\ ). Phew!

sunny
  • 1,156
  • 8
  • 15
0

I would try this:

preg_match('/^\/.*(\d+_\d+_\d+_\d+)\/.*$/', $file, $matches);
pokero
  • 1,009
  • 3
  • 13
  • 27
  • THis doesn't match the same things that OP wants. – Toto Apr 04 '14 at 09:04
  • How so? It looks to me like he wants the (\d+_\d+_\d+_\d+) part? – pokero Apr 04 '14 at 09:05
  • He want the delimiters to be slash `/` or backslash `\` also the numbers are between delimiters (not preceded by any char). And why do you put `.*$` at the end? – Toto Apr 04 '14 at 09:11
  • Ah, OK - then maybe preg_match('/^\/.*\/(\d+_\d+_\d+_\d+)\//', $file, $matches); would do the trick (just added in an extra delimiter before the digits start. I suppose .*$ is not actually needed then, good point. – pokero Apr 04 '14 at 09:40