At last a documentation on how to use my RegEx Extensions! It is also intended for those who have prior knowledge of Regular Expressions. The extensions use inbuilt C++ regex functions which receive unaltered Regular Expressions you pass to them, so if you know what you are doing you should have no problems. Both extensions are called with callExtension command which takes a single string as an argument which then passed to the extension.

_result = “extention” callExtension “arguments”;

The biggest challenge I had was to think of a way to pass all arguments to the .dll in a single string, let the .dll understand how to parse it and yet make it universal. For example if I use ‘:’ to separate arguments like many do, this might get problematic as ‘:’ has also special meaning in RegEx.

Syntax

regex_match<separator><regex><separator><subject>

  • <separator> - a single character, unique to <regex>
  • <regex> – a valid Regular Expression
  • <subject> – a part to which <regex> will be applied

regex_replace<separator><regex><separator><replacement><separator><subject>

  • <separator> - a single character, unique to <regex> and <replacement>
  • <regex> - a valid Regular Expression
  • <replacement> – a replacement format
  • <subject> - a part to which <regex> and <replacement> will be applied

The separator could be any character as long as it does not interfere with your composed RegEx. Since you are the one composing the Regular Expression in the first place, you can easily decide on what separator to use. For example in most cases you can just use traditional ‘/’:

_result = "regex_match" callExtension "/\w+(?=\s)/hello beautiful world";

The above reads as: match all words followed by space (but not the space) in hello beautiful world. RegEx returns: [hello, beautiful]. However if you were to parse http://killzonekid.com and include ‘/’ in RegEx, a different separator must be used as ‘/’ separator could interfere with RegEx. In this case I chose ‘|’:

_result = "regex_replace" callExtension "|http\:\/\/||http://killzonekid.com";

The above reads as: replace http:// in http://killzonekid.com with nothing. RegEx returns: killzonekid.com. If you have ” in your RegEx you can wrap your argument string in ‘ instead so nothing interferes and vice versa.

_result = "regex_match" callExtension '|"tro.{5}"|["trololol","tro","lol"]';

The above reads: match all instances of followed by tro followed by any 5 characters followed by in ["trololol","tro","lol"]. RegEx returns: ["trololol"].

Return

Although there is a regex_match command in C++ and I used it initially for a simple match, I switched to regex_search and modified its behaviour to suit ArmA needs better, this is why extension is still called regex_match.

regex_match

  • returns [match1,match2,match3...] – if matches are found
  • returns [] – if no match is found

So if you need a simple yes or no match answer, you can check if the result is or isn’t “[]”. If however you also need to access matches, you can call compile the result. Make sure that the output is a valid array if you do so. [tree,bush,tower] is not a valid array (unless tree, bush and tower are existing variables), ["tree","bush","tower"] is.

regex_replace

  • returns the subject, modified according to replacement rules – if match is found
  • returns original subject – if no match is found

Security

The callExtension command takes STRING and returns STRING. If you do not go beyond the STRING handling, you can use these extensions on the clients as well as on the server. However, the moment you decide to call compile the .dll return, you should know that at the moment there is no way of stopping someone from replacing a .dll on the client with a .dll of their own, and so you cannot trust the return from client .dlls (call compiling untrusted .dll return could give a hacker full access to your mission). In simple words: limit such use to server only while BIS is working on a solution.

Examples

I’m just going to give you a couple of practical examples showing why RegEx is so much needed in ArmA 3. Let’s say you have spawn markers placed all over the map and you need to grab only respawn_west markers. No problem! Turn allMapMarkers array into string and match only marker names starting with ‘respawn_west’:

/* allMapMarkers [ "respawn_west_1", "respawn_west_2", "respawn_west_3", "respawn_east_1", "respawn_guerrila_1", "respawn_civilian_1" ] */ _result = call compile ( "regex_match" callExtension format [ '/"respawn_west.*?"/%1', allMapMarkers ] ); //Result: ["respawn_west_1","respawn_west_2","respawn_west_3"]

I can assure you this method is one thousand hundred millions times faster and more efficient than current method used in ArmA 3.  Let’s say you have an array of numbers and you need to pick greatest number from it. No problem! Turn array into string, replace all commas with max command so that the whole thing looks like [5 max 17 max 3 max 66….max 77], call compile it and take the value of resulting single array element:

_array = [5,17,3,66,22,110,41,80,100,29,77]; _result = (call compile ( "regex_replace" callExtension format [ "/,/ max /%1", _array ] )) select 0; //Result: 110

Again mega fast and efficient. As you can see using RegEx can speed up and optimise your SQF scripts significantly. And as I mentioned earlier both extensions use native C++ regex library, so theoretically they can be added to ArmA 3 on the engine level easily and turned into scripting commands. Ah well, let’s wait and see how it goes with ArmA 3 further development.

KK's regex_match.dll Emulation Tool 
Input String Output String  
   

KK's regex_replace.dll Emulation Tool 
Input String Output String  
   

Enjoy,
KK