Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

Both of the following return True:

StringMatchQ["foo\"bar", RegularExpression[".*\".*"]]


StringMatchQ["foo\"bar", RegularExpression[".*\\\".*"]]

Which is more correct? Also what about

StringMatchQ["foo\\bar", RegularExpression[".*\\\\.*"]]
StringMatchQ["foo\\bar", RegularExpression[".*\\.*"]]
share|improve this question

2 Answers 2

up vote 10 down vote accepted

Short Version: Use ".*\".*" to match an embedded quote, ".*\\\\.*" to match an embedded backslash.

This question deals with two distinct syntaxes -- Mathematica string syntax and regular expression syntax. Both syntaxes use \ as an escape character, so we'll need separate the two levels to see what is happening.

First, let's deal with the Mathematica syntax. In Mathematica strings, both \ and " must be escaped by a preceding backslash. Mathematica interprets the exhibited strings as follows:

Mathematica Syntax          String Content
  ".*\".*"                    .*".*
  ".*\\\".*"                  .*\".*
  ".*\\.*"                    .*\.*
  ".*\\\\.*"                  .*\\.*

Having stripped away the Mathematica layer, the questions are now reduced to...

Are the regular expressions .*".* and .*\".* equivalent?

Yes.

Mathematica uses PCRE to implement its regular expressions. The key point concerns the meaning of \". Quoting from the PCRE manual page:

[...] only ASCII numbers and letters have any special meaning after a backslash. All other characters [...] are treated as literals.

Since " has no special regular expression meaning, \" is equivalent to ". Therefore .*".* and .*\".* are equivalent expressions. The shorter version is more common (Mathematica syntax: ".*\".*").

Are the regular expressions .*\.* and .*\\.* equivalent?

No!

The same PCRE backslash rule applies here. \. is interpreted as a literal . and \\ is interpreted as a literal backslash. So, the first regular expression, .*\.*, means zero or more characters, followed by zero or more literal periods. The second regular expression, .*\\.* means zero or more characters, followed by a literal backslash, followed by zero or more characters. The two expressions have different meanings!

The following examples show that the two expressions are not equivalent (take heed of the switch back to Mathematica string syntax):

$r1 = RegularExpression[".*\\.*"];

StringMatchQ["abc", $r1]      (* True *)

StringMatchQ["abc...", $r1]   (* True *)

StringMatchQ["abc\\def", $r1] (* True *)


$r2 = RegularExpression[".*\\\\.*"];

StringMatchQ["abc", $r2]      (* False *)

StringMatchQ["abc...", $r2]   (* False *)

StringMatchQ["abc\\def", $r2] (* True *)

For the most part, the first regular expression can be simplified to .*. The second, however, is already in the simplest form assuming that one wants to match a string that contains a backslash.

share|improve this answer
    
Thanks for the detailed explanation. +1 –  Matariki Jun 24 '12 at 1:08

I am not sure if this qualifies for an answer but it is too long for a comment therefore I put it here. Feel free to delete. In the examples the string matches the regular expression, meaning the result is not empty. Looking at the output we get

StringCases["foo\"bar", RegularExpression[".*\".*"]] // InputForm

(* {"foo\"bar"} *)

StringCases["foo\"bar", RegularExpression[".*\\\".*"]] // InputForm

(* {"foo\"bar"} *)

I used InputForm here to get the backslash in the output otherwise the String would suppress it and only show the double quotes. Why the second case matches the backslash I am not quite certain. It is arguable there but its function is to escape the double quotes. I would therefore argue that the first form is the correct form. Maybe someone with some indepth knowledge of Mma's string handling can shed some light on this.

In the second example we get the following:

StringCases["foo\\bar", RegularExpression[".*\\.*"]] // InputForm

(* {"foo\\bar", ""} *)

StringCases["foo\\bar", RegularExpression[".*\\\\.*"]] // InputForm

(* {"foo\\bar"} *) 

The correct form is here the second as a literal backslash has to be escaped with \\\\ which gives the correct result.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.