Skip to content

Commit 60295ff

Browse files
committed
DSL: add System.regex_match()
refs #7587
1 parent a65f2d6 commit 60295ff

File tree

4 files changed

+89
-0
lines changed

4 files changed

+89
-0
lines changed

doc/18-library-reference.md

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -587,6 +587,65 @@ true
587587
false
588588
```
589589

590+
### regex\_match <a id="global-functions-regex_match"></a>
591+
592+
Signature:
593+
594+
```
595+
function regex_match(pattern, value)
596+
```
597+
598+
If the regular expression `pattern` matches the string `value`,
599+
returns an array with the first match inside the whole string
600+
and the submatches of the match declared with parentheses.
601+
602+
Otherwise returns null.
603+
604+
Examples:
605+
606+
```
607+
$ icinga2 console
608+
Icinga 2 (version: v2.13.0)
609+
<1> => regex_match("foo", "bar")
610+
null
611+
<2> => regex_match("foo", "foo")
612+
[ "foo" ]
613+
<3> => regex_match("f(o)o", "foo")
614+
[ "foo", "o" ]
615+
```
616+
617+
```
618+
object Host "example.com" {
619+
check_command = "passive"
620+
621+
vars.http_urls = [
622+
"http://monitor.example.com/icingaweb2",
623+
"https://logs.example.com",
624+
"http://cloud.example.com:5000"
625+
]
626+
}
627+
628+
apply Service "http-" for (url in host.vars.http_urls) {
629+
check_command = "http"
630+
631+
var match = regex_match({{{http(s?)://([^:/]+)((?::\d+)?)((?:/.*)?)}}}, url)
632+
633+
if (match[1]) {
634+
vars.http_ssl = true
635+
}
636+
637+
vars.http_address = match[2]
638+
639+
if (match[3]) {
640+
vars.http_port = match[3].substr(1)
641+
}
642+
643+
if (match[4]) {
644+
vars.http_uri = match[4]
645+
}
646+
}
647+
```
648+
590649
### sleep <a id="global-functions-sleep"></a>
591650

592651
Signature:

lib/base/scriptutils.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,15 @@
1818
#include <boost/regex.hpp>
1919
#include <algorithm>
2020
#include <set>
21+
#include <utility>
2122
#ifdef _WIN32
2223
#include <msi.h>
2324
#endif /* _WIN32 */
2425

2526
using namespace icinga;
2627

2728
REGISTER_SAFE_FUNCTION(System, regex, &ScriptUtils::Regex, "pattern:text:mode");
29+
REGISTER_SAFE_FUNCTION(System, regex_match, &ScriptUtils::RegexMatch, "pattern:text");
2830
REGISTER_SAFE_FUNCTION(System, match, &ScriptUtils::Match, "pattern:text:mode");
2931
REGISTER_SAFE_FUNCTION(System, cidr_match, &ScriptUtils::CidrMatch, "pattern:ip:mode");
3032
REGISTER_SAFE_FUNCTION(System, len, &ScriptUtils::Len, "value");
@@ -148,6 +150,27 @@ bool ScriptUtils::Regex(const std::vector<Value>& args)
148150
}
149151
}
150152

153+
Array::Ptr ScriptUtils::RegexMatch(const String& pattern, const String& text)
154+
{
155+
boost::regex expr (pattern.GetData());
156+
boost::smatch what;
157+
158+
if (!boost::regex_search(text.GetData(), what, expr)) {
159+
return nullptr;
160+
}
161+
162+
Array::Ptr res = new Array();
163+
ObjectLock oLock (res);
164+
165+
res->Reserve(what.size());
166+
167+
for (auto& submatch : what) {
168+
res->Add(String(submatch.str()));
169+
}
170+
171+
return std::move(res);
172+
}
173+
151174
bool ScriptUtils::Match(const std::vector<Value>& args)
152175
{
153176
if (args.size() < 2)

lib/base/scriptutils.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ class ScriptUtils
2424
static double CastNumber(const Value& value);
2525
static bool CastBool(const Value& value);
2626
static bool Regex(const std::vector<Value>& args);
27+
static Array::Ptr RegexMatch(const String& pattern, const String& text);
2728
static bool Match(const std::vector<Value>& args);
2829
static bool CidrMatch(const std::vector<Value>& args);
2930
static double Len(const Value& value);

test/config-ops.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,12 @@ BOOST_AUTO_TEST_CASE(advanced)
158158
expr = ConfigCompiler::CompileText("<test>", R"(regex("^Hello", "Hello World"))");
159159
BOOST_CHECK(expr->Evaluate(frame).GetValue());
160160

161+
expr = ConfigCompiler::CompileText("<test>", R"(regex_match("f(o)o", "foo") == [ "foo", "o" ])");
162+
BOOST_CHECK(expr->Evaluate(frame).GetValue());
163+
164+
expr = ConfigCompiler::CompileText("<test>", R"(var nl = regex_match("f(o)o", "bar"); nl == null && typeof(nl) == Object)");
165+
BOOST_CHECK(expr->Evaluate(frame).GetValue());
166+
161167
expr = ConfigCompiler::CompileText("<test>", "__boost_test()");
162168
BOOST_CHECK_THROW(expr->Evaluate(frame).GetValue(), ScriptError);
163169

0 commit comments

Comments
 (0)