DSL: add System.regex_match()

refs #7587
This commit is contained in:
Alexander A. Klimov 2020-06-09 10:46:48 +02:00
parent a65f2d6b41
commit 60295ffc44
4 changed files with 89 additions and 0 deletions

View File

@ -587,6 +587,65 @@ true
false
```
### regex\_match <a id="global-functions-regex_match"></a>
Signature:
```
function regex_match(pattern, value)
```
If the regular expression `pattern` matches the string `value`,
returns an array with the first match inside the whole string
and the submatches of the match declared with parentheses.
Otherwise returns null.
Examples:
```
$ icinga2 console
Icinga 2 (version: v2.13.0)
<1> => regex_match("foo", "bar")
null
<2> => regex_match("foo", "foo")
[ "foo" ]
<3> => regex_match("f(o)o", "foo")
[ "foo", "o" ]
```
```
object Host "example.com" {
check_command = "passive"
vars.http_urls = [
"http://monitor.example.com/icingaweb2",
"https://logs.example.com",
"http://cloud.example.com:5000"
]
}
apply Service "http-" for (url in host.vars.http_urls) {
check_command = "http"
var match = regex_match({{{http(s?)://([^:/]+)((?::\d+)?)((?:/.*)?)}}}, url)
if (match[1]) {
vars.http_ssl = true
}
vars.http_address = match[2]
if (match[3]) {
vars.http_port = match[3].substr(1)
}
if (match[4]) {
vars.http_uri = match[4]
}
}
```
### sleep <a id="global-functions-sleep"></a>
Signature:

View File

@ -18,6 +18,7 @@
#include <boost/regex.hpp>
#include <algorithm>
#include <set>
#include <utility>
#ifdef _WIN32
#include <msi.h>
#endif /* _WIN32 */
@ -25,6 +26,7 @@
using namespace icinga;
REGISTER_SAFE_FUNCTION(System, regex, &ScriptUtils::Regex, "pattern:text:mode");
REGISTER_SAFE_FUNCTION(System, regex_match, &ScriptUtils::RegexMatch, "pattern:text");
REGISTER_SAFE_FUNCTION(System, match, &ScriptUtils::Match, "pattern:text:mode");
REGISTER_SAFE_FUNCTION(System, cidr_match, &ScriptUtils::CidrMatch, "pattern:ip:mode");
REGISTER_SAFE_FUNCTION(System, len, &ScriptUtils::Len, "value");
@ -148,6 +150,27 @@ bool ScriptUtils::Regex(const std::vector<Value>& args)
}
}
Array::Ptr ScriptUtils::RegexMatch(const String& pattern, const String& text)
{
boost::regex expr (pattern.GetData());
boost::smatch what;
if (!boost::regex_search(text.GetData(), what, expr)) {
return nullptr;
}
Array::Ptr res = new Array();
ObjectLock oLock (res);
res->Reserve(what.size());
for (auto& submatch : what) {
res->Add(String(submatch.str()));
}
return std::move(res);
}
bool ScriptUtils::Match(const std::vector<Value>& args)
{
if (args.size() < 2)

View File

@ -24,6 +24,7 @@ public:
static double CastNumber(const Value& value);
static bool CastBool(const Value& value);
static bool Regex(const std::vector<Value>& args);
static Array::Ptr RegexMatch(const String& pattern, const String& text);
static bool Match(const std::vector<Value>& args);
static bool CidrMatch(const std::vector<Value>& args);
static double Len(const Value& value);

View File

@ -158,6 +158,12 @@ BOOST_AUTO_TEST_CASE(advanced)
expr = ConfigCompiler::CompileText("<test>", R"(regex("^Hello", "Hello World"))");
BOOST_CHECK(expr->Evaluate(frame).GetValue());
expr = ConfigCompiler::CompileText("<test>", R"(regex_match("f(o)o", "foo") == [ "foo", "o" ])");
BOOST_CHECK(expr->Evaluate(frame).GetValue());
expr = ConfigCompiler::CompileText("<test>", R"(var nl = regex_match("f(o)o", "bar"); nl == null && typeof(nl) == Object)");
BOOST_CHECK(expr->Evaluate(frame).GetValue());
expr = ConfigCompiler::CompileText("<test>", "__boost_test()");
BOOST_CHECK_THROW(expr->Evaluate(frame).GetValue(), ScriptError);