Haxe Code Cookbook
Haxe programming cookbookBeginnerUsing regular expressions

Using regular expressions

Reading time: 2.5 minutes

In Haxe a regular expression starts with ~/ and ends with a single / and is of type EReg.

var regexp:EReg = ~/world/;

trace(regexp.match("hello world"));
// true : 'world' was found in the string

trace(regexp.match("hello")); 
// false : 'world' is not found in the string

Add flags with ending with adding the flag after the ending /.

var regexp:EReg = ~/world/ig; // case insensitive matching + global search

trace(regexp.match("HELLO WORLD"));
// true : 'world' was found in the string

Regular expressions with a dynamic pattern can be created by using the EReg constructor as follows:

var regexp:EReg = new EReg("world", "i"); // case insensitive matching 

trace(regexp.match("HELLO WORLD"));
// true : 'world' was found in the string

Replacing text

Simple text replacement can be done in several ways, even without regular expressions. Take this example where we replace "hello world" to "happy world":

var message = "hello world";
trace(StringTools.replace(message, "hello", "happy")); 
// "happy world"

The equivalent using regular expressions would be:

var message = "hello world";
var ereg:EReg = ~/hello/;
trace(ereg.replace(message, "happy")); 
// "happy world"

Now something what is interesting of regular expressions is that you can search and use the matched result in the replacement. For example, lets convert "high to low" to "low and high". We search for "high" and anything after that until we find "low". Since we use groups using round brackets, "$1" stands for the first matched group, which is the word "high".

var message = "high to low";
var ereg:EReg = ~/(high).+?(low)/;
trace(ereg.replace(message, "$2 and $1")); 
// "low and high"

Iterating on matched parts

Sometimes you want to deal with the specific parts or even the parts left or right of the search:

Note the matched function requires an index. Use 0 to match the whole substring, the index 1 and higher corresponds to the n-th set of parentheses in the regular expression. If no such sub-group exists in the pattern, an exception will be thrown.

var message = "important message: Haxe is great";
var ereg:EReg = ~/(message).+?(is)/;

if (ereg.match(message)) { 
  trace(ereg.matched(1)); // message
  trace(ereg.matched(2)); // is
  trace(ereg.matchedLeft()); // important 
  trace(ereg.matchedRight()); //  great
}

Note that the match method modifies the internal state.

The matchedRight can be very useful to iterate on the matches in case there are multiple results:

var message = "row row row your boat";
var ereg:EReg = ~/(row)/;

while (ereg.match(message)) { 
  trace(ereg.matched(1)); 
  message = ereg.matchedRight();
}
// row
// row
// row

More convenient would be to wrap this in a utility function that returns the results as Array. This also allows you to count the results.

function getMatches(ereg:EReg, input:String, index:Int = 0):Array<String> {
  var matches = [];
  while (ereg.match(input)) {
    matches.push(ereg.matched(index)); 
    input = ereg.matchedRight();
  }
  return matches;
}

// Test it out
var message = "row row row your boat";
var matches = getMatches(~/(row)/, message);
trace(matches); // [row,row,row]
trace(matches.length); // 3

Let's take a more real-life example, you can make an array with objects out of the matches like this:

// search for a number, then a space, then everything until newline character or end of input is found
function getFruits(input:String):Array<{amount:Int, fruit:String}> {
  var ereg = ~/(\d{1,2})\s(.+?)(\n|$)/g; 
  var list = [];
  while (ereg.match(input)) {
    list.push({
      amount: Std.parseInt(ereg.matched(1)),
      fruit: ereg.matched(2),
    }); 
    input = ereg.matchedRight();
  }
  return list;
}

// Test it out with a multiline string
var fruits = "1 Apple
    2 Bananas
       3 Pears
      1 Tomato";

trace(getFruits(fruits)); 
// [{amount:1, fruit:Apple}, {amount:2, fruit:Bananas}, {amount:3, fruit:Pears}, {amount:1, fruit:Tomato}]

Mapping results

In the following example we replace each match on a string using the EReg.map function and trace the replaced output.

var ereg:EReg = ~/(hello)/i;
var message = "hello world";
trace(ereg.map(message, function(e) return "happy"));
// happy world

External resources:

Haxe resources:


Contributors:
aszasz
arperry
Mark Knol
Last modified:
Created:
Category:  Beginner
Tags: