String replacement in ASL

The Smarts/IONIX ASL language does not have a built-in function for replacing one sub-string in a string with another. However, this is quite a common requirement. Here's an example of how it can be done.

The rule is typically called like this..

str1 = "The quick brown fox jumped over the lazy dog";
str2 = REPLACE_FIRST(str1, "fox", "WOLF");
print(str2);

And here is the code:

// Replace the first occurrence of s2 in s1 with s3
REPLACE_FIRST(s1, s2, s3) {
        local part1; local part2;
        input = s1;
        part1: { .. s2 }? .
        part2: { rep(char|fs) }
} do {
        if (part1 == "") {
                return str;
        } else {
                return substring(part1, 0, sizeof(part1)-sizeof(s2)).s3.part2;
        }
}

 The rule uses ASL's string parsing features, and works as follows.

  • It causes the contents of the s1 string to (temporarily) become the input buffer being parsed.
  • It searches for the s2 string in the updated input buffer, and places all characters from the start, up-to and including the s2 match into part1. If the s2 string is not found then part1 will contain an empty string (that's what the "?" does for us).
  • The "." at the end of the "part1" line ensures that if there is any white space after the s2 string, this does not get discarded.
  • The remainder of the string is copied into "part2".
  • The "do" code then returns the result, which is either a copy of the original s1 (if s2 wasnt found - and hence part1 is empty), or a concatenation of:
    • The contents of part1, with the s2 remove from the end
    • The s3 string
    • The contents of part2

 An alternative, more complex form of the rule can be used to replace all occurrences rather than just the first..

// Replace all occurrences of s2 in s1 with s3
REPLACE_ALL(s1, s2, s3) {
local found; local remainder; local rtn; input = s1; do { rtn = ""; } rep(.{ { found: { .. s2 } do { rtn = rtn . substring(found, 0, sizeof(found)-sizeof(s2)) . s3; } } | { remainder: rep(.{char|fs}) do { rtn = rtn . remainder; } } })? } do { return rtn; }

 This works in a similar way to the first script, but uses the trick of having a "do" block inside "rep" statement

Scroll to Top