Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What exactly does a Regex created with Regex.fromLiteral() match?

Tags:

regex

kotlin

I've created a very simple match-all Regex with Regex.fromLiteral(".*").

According to the documentation: "Returns a literal regex for the specified literal string."

But I don't really get what "for the specified literal string" is supposed to mean.

Consider this example:

fun main(args: Array<String>) {
    val regex1 = ".*".toRegex()
    val regex2 = Regex.fromLiteral(".*")
    println("regex1 matches abc: " + regex1.matches("abc"))
    println("regex2 matches abc: " + regex2.matches("abc"))
    println("regex2 matches .* : " + regex2.matches(".*"))  
}

Output:

regex1 matches abc: true
regex2 matches abc: false
regex2 matches .* : true

so apparently (and contrary to my expectations), Regex.fromLiteral() and String.toRegex() behave completely different (I've tried dozens of different arguments to regex2.matches() - the only one that returned true was .*)

Does this mean that a Regex created with Regex.fromLiteral() always matches only the exact string it was created with?

If yes, what are possible use cases for such a Regex? (I can't think of any scenario where that would be useful)

like image 972
Frank Schmitt Avatar asked Jul 11 '17 13:07

Frank Schmitt


1 Answers

Yes, it does indeed create a regex that matches the literal characters in the String. This is handy when you're trying to match symbols that would be interpreted in a regex - you don't have to escape them this way.

For example, if you're looking for strings that contain .*[](1)?[2], you could do the following:

val regex = Regex.fromLiteral(".*[](1)?[2]")

regex.containsMatchIn("foo")                  // false
regex.containsMatchIn("abc.*[](1)?[2]abc")    // true

Of course you can do almost anything you can do with a Regex with just regular String methods too.

val literal = ".*[](1)?[2]"
literal == "foo"                       // equality checks
literal in "abc.*[](1)?[2]abc"         // containment checks
"some string".replace(literal, "new")  // replacements

But sometimes you need a Regex instance as a parameter, so the fromLiteral method can be used in those cases. Performance of these different operations for different inputs could also be interesting for some use cases.

like image 117
zsmb13 Avatar answered Nov 01 '22 23:11

zsmb13