replaceAllMapped matches with span elements - regex

I want to replace all matched strings after regExp with same strings in span elements. Is this possible?
I want to do something like that:
final text = message.replaceAllMapped(exp, (match) => '<span>exp, (match)</span>');

You may use String#replaceAllMapped like this:
final exp = new RegExp(r'\d+(?:\.\d+)?');
String message = 'test 40.40 test 20.20';
final text = message.replaceAllMapped(exp,
(Match m) => "<span>${m[0]}</span>");
print(text);
Output: test <span>40.40</span> test <span>20.20</span>
Here, m is the Match object that the regex engine finds and passes to the arrow method where the first item in the m array is inserted in between <span> and </span> inside an interpolated double quoted string literal.

Related

Regex to find all Strings enclosed between two Strings in Dart

I'd like to find all occurrences of strings in a long string which are placed between a set of two specific strings.
For eg.
String s = "abcdText('hello')abcd efghText('world')";
The regex pattern of strings would be Text(' and next ' and the results should be the List of strings enclosed between the pattern. Hence the expected output should be:
[hello, world]
After some searches, I found this. This explains my use case but it is in PHP and only meant to find digits.
You can try this way :
String myString = "abcdText('hello')abcd efghText('world')";
RegExp exp = RegExp(r"\('(.*?)'\)");
List<String> _list =[];
for (var m in exp.allMatches(myString)) {
_list.add(m[1].toString());
}
print(_list);
EDIT
String myString = "abcdText('hello')abcd efghText('world')";
RegExp exp = RegExp(r"Text\('(.*?)'\)");
List<String> _list =[];
for (var m in exp.allMatches(myString)) {
_list.add(m[1].toString());
}
print(_list);

How to use Regex to parse variable length string in Google Application Scripts

Trying to extract the alphanumeric parts of a variable length string with a known pattern using Regex in Google Application Scripts. Pattern repeats n times as follows (XXXs are groups of Alphanumeric characters):
XX-XXX-X-XX-XX-........ for example ABC-AB or ABCD-AB-ABC-AA
I want to extract the alphanumeric parts into an Array if possible like e[0] = ABCD e[1] = AB e[2] = ABC .....
I tried repeated \w+ but that requires knowing the possible lengths of string. See below. Is there a way for Regex to process varying size strings? See my example code below:
var data1 = 'ABC-AB';
var data2 = 'ABCD-AB-ABCD-AA';
var regex1 = new RegExp(/(\w+)-(\w+)/);
var regex2 = new RegExp(/(\w+)/);
e = regex1.exec(data1); //stores ABC and AB as separate array elements.
This is fine but won't work on a string with larger size
e = regex2.exec(data2); //stores ABCD only as a single array element "ABCD"
To match any length of kebab case letters:
var regex1 = new RegExp(/\w+(-\w+)*/)
For each of the matches found, split the result on dashes to get your array.
var array = found.split("-")

Find index locations by regex pattern and replace them with a list of indexes in Scala

I have strings in this format:
object[i].base.base_x[i] and I get lists like List(0,1).
I want to use regular expressions in scala to find the match [i] in the given string and replace the first occurance with 0 and the second with 1. Hence getting something like object[0].base.base_x[1].
I have the following code:
val stringWithoutIndex = "object[i].base.base_x[i]" // basically this string is generated dynamically
val indexReplacePattern = raw"\[i\]".r
val indexValues = List(0,1) // list generated dynamically
if(indexValues.nonEmpty){
indexValues.map(row => {
indexReplacePattern.replaceFirstIn(stringWithoutIndex , "[" + row + "]")
})
else stringWithoutIndex
Since String is immutable, I cannot update stringWithoutIndex resulting into an output like List("object[0].base.base_x[i]", "object[1].base.base_x[i]").
I tried looking into StringBuilder but I am not sure how to update it. Also, is there a better way to do this? Suggestions other than regex are also welcome.
You couldloop through the integers in indexValues using foldLeft and pass the string stringWithoutIndex as the start value.
Then use replaceFirst to replace the first match with the current value of indexValues.
If you want to use a regex, you might use a positive lookahead (?=]) and a positive lookbehind (?<=\[) to assert the i is between opening and square brackets.
(?<=\[)i(?=])
For example:
val strRegex = """(?<=\[)i(?=])"""
val res = indexValues.foldLeft(stringWithoutIndex) { (s, row) =>
s.replaceFirst(strRegex, row.toString)
}
See the regex demo | Scala demo
How about this:
scala> val str = "object[i].base.base_x[i]"
str: String = object[i].base.base_x[i]
scala> str.replace('i', '0').replace("base_x[0]", "base_x[1]")
res0: String = object[0].base.base_x[1]
This sounds like a job for foldLeft. No need for the if (indexValues.nonEmpty) check.
indexValues.foldLeft(stringWithoutIndex) { (s, row) =>
indexReplacePattern.replaceFirstIn(s, "[" + row + "]")
}

Selectively uppercasing a string

I have a string with some XML tags in it, like:
"hello <b>world</b> and <i>everyone</i>"
Is there a good Scala/functional way of uppercasing the words, but not the tags, so that it looks like:
"HELLO <b>WORLD<b> AND <i>EVERYONE</i>"
We can use dustmouse's regex to replace all the text in/outside XML tags with Regex.replaceAllIn. We can get the matched text with Regex.Match.matched which then can easily be uppercased using toUpperCase.
val xmlText = """(?<!<|<\/)\b\w+(?!>)""".r
val string = "hello <b>world</b> and <i>everyone</i>"
xmlText.replaceAllIn(string, _.matched.toUpperCase)
// String = HELLO <b>WORLD</b> AND <i>EVERYONE</i>
val string2 = "<h1>>hello</h1> <span>world</span> and <span><i>everyone</i>"
xmlText.replaceAllIn(string2, _.matched.toUpperCase)
// String = <h1>>HELLO</h1> <span>WORLD</span> AND <span><i>EVERYONE</i>
Using dustmouse's updated regex :
val xmlText = """(?:<[^<>]+>\s*)(\w+)""".r
val string3 = """<h1>>hello</h1> <span id="test">world</span>"""
xmlText.replaceAllIn(string3, m =>
m.group(0).dropRight(m.group(1).length) + m.group(1).toUpperCase)
// String = <h1>>hello</h1> <span id="test">WORLD</span>
Okay, how about this. It just prints the results, and takes into consideration some of the scenarios brought up by others. Not sure how to capitalize the output without mercilessly poaching from Peter's answer:
val string = "<h1 id=\"test\">hello</h1> <span>world</span> and <span><i>everyone</i></span>"
val pattern = """(?:<[^<>]+>\s*)(\w+)""".r
pattern.findAllIn(string).matchData foreach {
m => println(m.group(1))
}
The main thing here is that it is extracting the correct capture group.
Working example: http://ideone.com/2qlwoP
Also need to give credit to the answer here for getting capture groups in scala: Scala capture group using regex

Cannot retrive a group from Scala Regex match

I am struggling with regexps in Scala (2.11.5), I have a followin string to parse (example):
val string = "http://sth.com/sth/56,57597,14058913,Article_title,,5.html"
I want to extract third numeric value in the string above (it needs to be third after a slash because there can be other groups following), in order to do that I have the following regex pattern:
val pattern = """\/\d+,\d+,(\d+)""".r
I have been trying to retrieve the group for the third sequence of digits, but nothing seems to work for me.
val matchList = pattern.findAllMatchIn(string).foreach(println)
val matchListb = pattern.findAllIn(string).foreach(println)
I also tried using matching pattern.
string match {
case pattern(a) => println(a)
case _ => "What's going on?"
}
and got the same results. Either whole regexp is returned or nothing.
Is there an easy way to retrieve a group form regexp pattern in Scala?
You can use group method of scala.util.matching.Regex.Match to get the result.
val string = "http://sth.com/sth/56,57597,14058913,Article_title,,5.html"
val pattern = """\/\d+,\d+,(\d+)""".r
val result = pattern.findAllMatchIn(string) // returns iterator of Match
.toArray
.headOption // returns None if match fails
.map(_.group(1)) // select first regex group
// or simply
val result = pattern.findFirstMatchIn(string).map(_.group(1))
// result = Some(14058913)
// result will be None if the string does not match the pattern.
// if you have more than one groups, for instance:
// val pattern = """\/(\d+),\d+,(\d+)""".r
// result will be Some(56)
Pattern matching is usually the easiest way to do it, but it requires a match on the full string, so you'll have to prefix and suffix your regex pattern with .*:
val string = "http://sth.com/sth/56,57597,14058913,Article_title,,5.html"
val pattern = """.*\/\d+,\d+,(\d+).*""".r
val pattern(x) = string
// x: String = 14058913