The following sections describe the standard types that are built into the interpreter.
NXSL is loose typed programming language. The system will automatically
determine each variable type, assign a certain type to a variable and convert a
variable type from one to another, if necessary. For example, a result for 3
+ "4"
will be 7
, because the system will automatically convert "4"
string into an integer. In case if the system is not able to automatically
convert a line into an appropriate integer, the operation will result in a
runtime error.
NXSL supports the following variable types:
-
integer (32 bit),
-
unsigned integer (32 bit),
-
integer (64 bit), unsigned integer (64 bit),
-
floating-point number,
-
string,
-
boolean,
-
array,
-
hash map,
-
object.
In addition to that, NXSL also supports a special variable type – NULL
.
This value represents a variable with no value. NULL
is the only possible
value of type NULL
. An attempt to perform any type of arithmetical or
string operations with NULL
variable will result in system runtime error.
It is possible to manually convert variable to a certain type, using a special
function, named depending on the variable type. For example, string(4)
.
That way it is also possible to convert NULL
type variables. Therefore, to
avoid runtime errors while processing NULL
type variables, it is advised to
use manual conversion.
NXSL does not require setting variable type beforehand. The only exception to
this is arrays. In case if an array is required, operator array
defines its
subsequent variables as arrays. Accessing variable which was not previously
assigned will return NULL
value.
Although NXSL has object type variables, it is not an object-oriented language. It is not possible to define classes or create objects at script level – only in extensions written in C++. Object type variables are used to return information about complex NetXMS objects, like nodes or events, in a convenient way. Please note that assigning object type variables actually holds reference to an object, so assigning object value to another variable does not duplicate actual object, but just copy reference to it.
To get a human-readable representation of a variable or expression type for
debugging, use the typeof()
function, and to get a class name for object
type variables, use classof()
function.
A string literal is where you specify the contents of a string in a program. There are few different string literal types:
-
"string" - string literal where some characters preceded by a backslash have special meaning. If you need to insert double quote character you should prepend it with backslash.
-
'string' - string literal with backslash being an ordinary character without special meaning. You cannot insert single quote character into such string literal.
-
""" Multi
line
string""" - string literal that can span multiple lines with backslash being an ordinary character.
The following character combinations are supported in "string" literals:
-
\b
- produces Backspace character -
\t
- produces Horizontal tab character -
\n
- produces Newline character -
\r
- produces Carriage return character -
'\xhh' - produces a character with code hh (where hh is two-digit hex number)
-
'\uhhhh' - produces a character with code hhhh (where hhhh is four-digit hex number). E.g.
\u2026
produces Greek small letter Mu (μ
) -
\\
- produces Backslash character (\
)
Any variable can be tested for truth value, for use in an if
or while
condition
or as operand of the Boolean operations below. The following values are considered false:
-
false
-
NULL
-
zero of any numeric type, for example,
0
,0.0
,0j
.
All other values are considered true
— so objects of various types and arrays are always true
.
Operations and built-in functions that have a Boolean result return boolean type. However,
there’s an exception to this due to optimizations related to short-circuit evaluation of
or
and and
operators. For or
, if first operand not boolean type, but it’s value is
considered true
, that operand will be returned as result. For and
, if first operand is
considered false
, that operand will be returned as result. This will not cause issues in
subsequent logical operations, as returned value will be correctly considered as true
or false
;
But when printing the result, it will not be converted to Boolean, so conversion
using boolean() function might be needed.
For example:
a = [1,2,3];
b = true;
c = a or b;
println(c); // will print "[1, 2, 3]" because first operand was returned by or operation
if (c) println("TRUE"); // will print "TRUE" as the array contained in c is considered as true
a = 0;
b = true;
c = a and b;
println(c); // will print "0" because first operand was returned by and operation
println(boolean(c)); // will print "false"
Variables in NXSL behave the same way as variables in most popular programming languages (C, C++, etc.) do, but in NXSL you don’t have to declare variables before you use them.
Scope of a variable can be either global (visible in any function in the
script) or local (visible only in the function within which it was defined).
Any variable is by default limited to the local function scope. Variable can be
declared global using global
operator.
For example:
x = 1;
myFunction();
function myFunction()
{
println("x * 2 = " .. x * 2);
}
This script will cause run time error Error 5 in line 6: Invalid operation
with NULL value
, because variable x
is local (in implicit main function)
and is not visible in function myFunction
. The following script will
produce expected result (prints x=1
):
global x = 1;
myFunction();
function myFunction()
{
println("x * 2 = " .. x * 2);
}
A function is a named code block that is generally intended to process
specified input values into an output value, although this is not always the
case. For example, the trace()
function takes variables and static text and
prints the values into server log. Like many languages, NXSL provides for
user-defined functions. These may be located anywhere in the main program or
loaded in from other scripts via the import keywords.
To define a function, you can use the following form:
function NAME ( ARGUMENTS ) BLOCK
where NAME
is any valid identifier, ARGUMENTS
is optional list of
argument names, and BLOCK
is code block.
To call a function you would use the following form:
NAME ( LIST )
where NAME
is identifier used in function definition, and LIST
is an
optional list of expressions passed as function arguments.
To give a quick example of a simple subroutine:
function message()
{
println("Hello!");
}
The first argument you pass to the function is available within the function as
$1
, the second argument is $2
, and so on. For example, this simple
function adds two numbers and prints the result:
function add()
{
result = $1 + $2;
println("The result was: " .. result);
}
To call the subroutine and get a result:
add(1, 2);
If you want named arguments, list of aliases for $1
, $2
, etc. can be
provided in function declaration inside the brackets:
function add(numberA, numberB)
{
result = numberA + numberB;
println("The result was: " .. result);
}
If parameter was not provided at function call, value of appropriate variable
will be NULL
.
Another option to name parameters is to provide named parameters inside of function. In this case leave braces of function empty and add names to function call. In this case parameters will be available in function as $parameterName.
Example:
func(param2: "text2", param1: "text1");
return 0;
function func()
{
println($param1); //Will print "text1"
println($param2); //Will print "text2"
}
The arguments received by script when it was launched are available in a global variable $ARGS, which is an array that contains all arguments. First argument available as $ARGS[1];
You can return a value from a function using the return
keyword:
function pct(value, total)
{
return value / total * 100.0;
}
When called, return immediately terminates the current function and returns the
value to the caller. If you don’t specify a value in return
statement or
function ends implicitly by reaching end of function’s block, then the return
value is NULL
.
NXSL handles script entry in 2 ways:
-
Explicit main() function
-
Implicit $main() function
If an explicitly defined main() exists, it will be called.
If an explicit main() doesn’t exist, an implicit $main() function will be created by the script interpreter and the script will enter at the $main() function.
The $main() function is constructed from code that is not a part of any other functions.
You can call functions from scripts that are stored in Script Library. One way is
to use the import
keyword accompanied by the name of the script:
import my_math_library;
println( add(1, 2) );
The other was is shown in this example:
println( my_math_library::add(1, 2) );
Strings are not objects, it’s a separate variable type. However, strings have methods and attributes described below
isEmpty ⇒ Boolean
-
Returns "true" if string is empty or "false" otherwise.
s = ""; println(s.isEmpty); // prints "true"
length ⇒ Integer
-
Returns number of characters in the string.
s = "1234567890"; println(s.length); // prints '10'
compareTo(string) ⇒ Integer
-
Compares two strings lexicographically (alphabetical order). Returns
-1
if the argument is a string lexicographically greater than this string,1
if the argument is a string lexicographically less than this string or0
if the argument is a string lexicographically equal to this string.
The is a difference to ==
comparison operator if strings contain numbers because
values are converted to numberic type prior to comparison.
println("a".compareTo("c")); // prints "-1" println("c".compareTo("a")); // prints "1" println("a".compareTo("aaa")); // prints "-1" println("aaa".compareTo("a")); // prints "1" println("100".compareTo("100.0")); // prints "-1" println("100" == "100.0"); // prints true
compareToIgnoreCase(string) ⇒ Integer
-
Same as
compareTo
, but ignoring the case.
println("aaa".compareToIgnoreCase("AAA")); // prints "0"
contains(string) ⇒ Boolean
-
Returns
true
if this string contains the argument string orfalse
otherwise.
println("aaa".contains("a")); // prints "true"
endsWith(string) ⇒ Boolean
-
Returns
true
if this string ends with the argument string orfalse
otherwise.
println("abc".endsWith("d")); // prints "false" println("Just a sentence".endsWith("a sentence")); // prints "true"
equalsIgnoreCase(string) ⇒ Boolean
-
Returns
true
if argument string is equal to this string ignoring the case orfalse
otherwise.
println("abc".equalsIgnoreCase("ABC")); // prints "true"
indexOf(string) ⇒ Integer
-
Returns index of first occurence of argument string in this string or
-1
if the argument is not a substring of the string.
println("ABC-DEF-GHI".indexOf("-")); // prints "3" println("ABC-DEF-GHI".indexOf("ABC")); // prints "0" println("ABC-DEF-GHI".indexOf("JKL")); // prints "-1"
lastIndexOf(string) ⇒ Integer
-
Returns index of last occurence of argument string in this string or
-1
if the argument is not a substring of the string.
println("ABC-DEF-GHI".lastIndexOf("-")); // prints "7" println("ABC-DEF-GHI".lastIndexOf("ABC")); // prints "0" println("ABC-DEF-GHI".lastIndexOf("JKL")); // prints "-1"
left(numberOfCharacters, paddingCharacter) ⇒ String
-
Returns left
numberOfCharacters
of this string. If string length is less thennumberOfCharacters
, result will be padded on the right.paddingCharacter
is optional, if not specified, space character will be used for padding.
println("ABCDEFGHI".left(2)); // prints "AB" println("123".left(5)); // prints "123 " println("123".left(5, "_")); // prints "123__"
replace(whatToReplace, replaceBy) ⇒ String
-
Returns string where all occurencies of
whatToReplace
are replaced withreplaceBy
.
println("A B C A D K L".replace("A", "<A>")); // prints "<A> B C <A> D K L"
right(numberOfCharacters, paddingCharacter) ⇒ String
-
Returns right
numberOfCharacters
of this string. If string length is less thennumberOfCharacters
, result will be padded on the left.paddingCharacter
is optional, if not specified, space character will be used for padding.
println("ABCDEFGHI".right(2)); // prints "HI" println("123".right(5)); // prints " 123" println("123".right(5, "_")); // prints "__123"
split(separator, trimWhitespace) ⇒ Array
-
Split string into array of strings at given separator.
trimWhitespace
parameter is optional and is false
by default. If set to
true
, space characters will be removed on both sides of strings produced by
splitting. This parameter was added in version 5.1.4.
println("ABC--DEF--GHI".split("--")); // prints "[ABC, DEF, GHI]" s = "Alice, Bob, Carol"; for (a : s.split(",")) println("|"..a.."|"); // Will print: // |Alice | // | Bob| // | Carol| s = "Alice , Bob, Carol"; for (a : s.split(",", true)) println("|"..a.."|"); // Will print: // |Alice| // |Bob| // |Carol|
startsWith(string) ⇒ Boolean
-
Returns
true
if this string starts with the argument string orfalse
otherwise.
println("abc".startsWith("d")); // prints "false" println("Just a sentence".startsWith("Just a")); // prints "true"
substring(position, numberOfCharacters) ⇒ String
-
Returns substring of this string starting from
position
and containingnumberOfCharacters
.
println("ABCDEFGHIJK".substring(0,3)); // prints "ABC" println("ABCDEFGHIJK".substring(6,3)); // prints "GHI" println("ABCDEFGHIJK".substring(6,10)); // prints "GHIJK"
toLowerCase() ⇒ String
-
Converts this string to lowercase.
println("ABC def".toLowerCase()); // prints "abc def"
toUpperCase() ⇒ String
-
Converts this string to uppercase.
println("ABC def".toUpperCase()); // prints "ABC DEF"
trim() ⇒ String
-
Returns this string with whitespace from both sides removed.
println("|" .. " ABC ".trim() .. "|") // prints "|ABC|"
trimLeft() ⇒ String
-
Returns this string with whitespace from left side removed.
println("|" .. " ABC ".trimLeft() .. "|") // prints "|ABC |"
trimRight() ⇒ String
-
Returns this string with whitespace from right side removed.
println("|" .. " ABC ".trimRight() .. "|") // prints "| ABC|"
An array in NXSL is actually an ordered map. A map is a type that associates
values
to keys
. This type is optimized for several different uses; it
can be treated as an array, list (vector), hash table (an implementation of a
map), dictionary, collection, stack, queue, and probably more. Nested arrays
are supported, so elements of an array can be themselves arrays.
A key
is 32-bit signed integer. When an array is created, its size is
not specified and its map can have empty spots in it. For example, an array can
have a element with a 0
key and an element with 4
key and no keys
in-between. Attempting to access an array key which has not been defined is the
same as accessing any other undefined variable: the result will be NULL
.
Arrays are not objects, it’s a separate variable type. However, arrays have methods and attributes described below.
Array elements can be accessed using [index
] operator. For example, to
access element with index 3
of array a
you should use
a[3];
To get subarray from the array use [a:b]
operator. This operator returns
subarray of an array from the element with index a
inclusive till the element
with index b
exclusive. If a
is omitted then subarray will be taken from the
start of the array and if b
is omitted then subarray will be taken till the
end of the array.
Example:
a = [1, 2, 3, 4];
a2 = a[1:3]; // a2 will be [2, 3]
a3 = a[1:]; // a3 will be [2, 3, 4]
New array can be created in two ways. First is to use array
operator.
This statement will create empty array and assign reference to it to variable a
.
array a;
You can then assign values to the array. Please note arrays in NXSL are sparse, so indices can contain gaps.
array a;
a[1] = 1;
a[2] = 2;
a[260] = 260;
println(a[1]); // will print 1
println(a); // will print "[1, 2, 260]"
Second way is to use [] construct to create array already populated with values.
This statement will create array with four elements at positions 0, 1, 2, and 3, and assign reference to this array to variable a.
// no need to use "array a;" here, since we are creating it directly
a = [1, 2, 3, 4];
println(a[0]); // will actually print 1, since 1 is the 0th member
println(a); // will print "[1, 2, 3, 4]"
Array initialization can also be used directly in expressions, like this:
function f()
{
return [2, "text", [1, 2, 3]];
}
In this example function f
returns array of 3 elements - number, text, and
another array of 3 numeric elements.
maxIndex ⇒ Integer
-
Returns highest index in the array.
a = [1, 2, 3]; println(a.maxIndex); // prints '2' println(a[a.maxIndex]); // prints '3'
minIndex ⇒ Integer
-
Returns lowest index in the array.
a = [1, 2, 3]; println(a.minIndex); // prints '0'
size ⇒ Integer
-
Returns number of elements in the array.
a = [1, 2, 3]; println(a.size); // prints '3'
append(newElement) ⇒ Integer
-
Appends new element to the array. Returns highest index in the array - that’s index of the appended element.
a = ["a","b","c"]; a.append("d"); println(a); // prints '[a, b, c, d]'
appendAll(anotherArray) ⇒ Integer
-
Appends elements of
anotherArray
to the array. Returns highest index in the array.
a = [1,2]; b = [3,4]; a.appendAll(b); println(a); // prints '[1, 2, 3, 4]'
indexOf(value) ⇒ Integer
-
Returns the index of first occurrence of the specified
value
or -1 ifvalue
is not found in the array.
a = ["Normal", "Warning", "Minor", "Major", "Critical"]; println(a.indexOf("Major")); // Prints "3"
join(separator) ⇒ void
-
.Parameters
separator |
String |
Separator between array elements |
Example | Name | Result |
---|---|---|
|
Spread operator |
Used when all elements from an object or array need to be included in a new array or object or should be applied one-by-one in a function call’s arguments list. |
sub sum(i, j, k) { return i + j + k; } data = %(10, 20, 30); println(sum(...data)); a = %("one", "two"); b = %("new", ...a);
Concatenated string
a = [1, 2, 3, 4]; println(a.join(";")); // will print "1;2;3;4" println(a.join("; ")); // will print "1; 2; 3; 4"
insert(index, newElement) ⇒ void
-
Inserts new element to the array at
index
. Indexes of existing elements that had index greater or equal toindex
are incremented.
array a; a[0] = "aaa"; a[10] = "ccc"; a.insert(5, "bbb"); println(a[0]); // prints "aaa" println(a[5]); // prints "bbb" println(a[11]); // prints "ccc" - because of the insert operation this element's index is now 11.
insertAll(index, anotherArray) ⇒ void
-
Inserts elements of
anotherArray
to the array atindex
. Indexes of existing elements that have index greater or equal toindex
are incremented.
a = [1,2]; b = [3,4]; a.insertAll(1,b); println(a); // prints '[1, 3, 4, 2]'
pop() ⇒ Element with highest index
-
Removes element with highest index from the array. Using
push(value)
andpop()
methods it’s possible to use array as a stack. Or, usinginsert(0,value)
andpop()
, array will work as FIFO queue.
a = []); a.push("one"); a.push("two"); println(a.pop()); println(a.pop());
push(newElement) ⇒ Integer
-
Same as
append()
. remove(index) ⇒ void
-
Removes element at specified
index
. Indexes of elements that have index greater or equal toindex
are decremented.
a = [1,2,3]; a.remove(0); println(a);
String representation of array can be obtained by using string(array)
function. The string representation consists of all array’s elements, enclosed
in square brackets (“[]”). Adjacent elements are separated by the characters
“, ” (a comma followed by a space).
Printed array is automatically converted to string.
a = [1, 2, 3, 4, 5, 6, 7];
println(a); // will print "[1, 2, 3, 4, 5, 6, 7]"
println(a .. " is an array"); // will print "[1, 2, 3, 4, 5, 6, 7] is an array"
println(["one", "two"]); // will print "[one, two]"
println([2, "text", [1, 2, 3]]); // will print "[2, text, [1, 2, 3]]"
Hash map allows to store data values in key:value pairs. A key is string. Numeric type can also be supplied as key, but it will be internally converted to string. Hash map cannot have two items with the same key. The values can be of any data type, including null, objects, arrays or hash maps.
Hash maps are not objects, it’s a separate variable type. However, hash maps have methods and attributes described below.
Array elements can be accessed using [key] operator. For example, to access element with key key of hash map h you should use
h["key"];
This statement will create an empty hash map and assign reference to in to variable h:
h = %{};
It’s also possible to create hash map already populated with values, e.g.:
h = %{"key":123, "another_key":456};
keys ⇒ Array
-
Returns array with keys of items in the hash map.
h = %{100:"value1", 101:"value2"}; println(h.keys); // prints '[100,101]'
size ⇒ Integer
-
Returns number of items in the hash map.
h = %{"a":null, "b":null, "c":null}; println(h.size); // prints '3'
values ⇒ Array
-
Returns array with values of items in the hash map.
h = %{"key1":123, "key2":456}; println(h.keys); // prints '[123,456]'
contains(key) ⇒ Boolean
-
Returns
true
, if hash map contains specified key orfalse
otherwise.
h = %{"key1":123, "key2":456}; println(h.contains("key2")); // prints 'true'
remove(key) ⇒ void
-
Removes item with specified
key
.
h = %{"key1":123, "key2":456}; h.remove("key1"); println(h); // prints '{key2=456}'
Hash Map can be converted to string. string(hash-map)
function is used to get string
representation of hash map. The string representation lists all key-value pairs
enclosed in curly brackets (“{}”). Value is separate from the key with equals sigh ("=").
Items are separated by the characters “, ” (a comma followed by a space).
Printed array is automatically converted to string.
h = %{"key1":123, "key2":456};
println("This is a hash map: " .. string(h));
println("Or we can just print it this way: " .. h);
An operator is something that you feed with one or more values, which yields another value.
Example | Name | Result |
---|---|---|
|
Negation |
Opposite of |
|
Addition |
Sum of |
|
Subtraction |
Difference between |
|
Multiplication |
Product of |
|
Division |
Quotient of |
|
Modulus |
Remainder of |
The division operator (/
) returns a float value unless the two operands are
integers (or strings that get converted to integers) and the numbers are evenly
divisible, in which case an integer value will be returned.
Calling modulus on float operands will yield runtime error.
The assignment operator is =
, which means that the left operand gets set to
the value of the expression on the rights (that is, "gets set to").
Example | Name | Result |
---|---|---|
|
Not |
Bits that are set in |
|
And |
Bits that are set in both operand are set. |
|
Or |
Bits that are set in either operand are set. |
|
Xor |
Bits that are set in only one operand are set. |
|
Shift left |
Shift the bits of |
|
Shift right |
Shift the bits of |
Comparison operators allow you to compare two values.
Example | Name | Result |
---|---|---|
|
Equal |
|
|
Not equal |
|
|
Less than |
|
|
Greater than |
|
|
Less than or equal to |
|
|
Greater than or equal to |
|
|
Match |
Array containing full match of |
|
Match |
Same as |
|
Match (case insensitive) |
Same as |
|
Like |
Compare string value to a pattern using wildcard characters. Two wildcard characters
are supported: |
|
Like (case insensitive) |
Same as |
Example:
println("aaa bbb ccc" ~= "b+") // prints "[bbb]"
println("Username: John" ~= "Username: (\w+)"); // prints "[Username: John, John]"
println("abc" like "?bc*"); // prints "true"
Note that strings which actually contain number are converted to numeric type prior to comparison. So, for example:
s1 = "1";
s2 = "1.0";
i = 1;
println(s1 == s2); // prints "true"
println(s1 == i); // prints "true"
NXSL supports C-style pre- and post-increment and decrement operators.
Example | Name | Result |
---|---|---|
|
Pre-increment |
Increments |
|
Post-increment |
Returns |
|
Pre-decrement |
Decrements |
|
Post-decrement |
Returns |
Example | Name | Result |
---|---|---|
|
Not |
|
|
Not |
Same as above. |
|
And |
|
|
And |
Same as above. |
|
Or |
|
|
Or |
Same as above. |
Example | Name | Result |
---|---|---|
|
Concatenation operator |
Returns the concatenation of its right and left arguments. |
|
Concatenating assignment operator |
Appends the argument on the right side to the argument on the left side. |
|
Substring operator |
Returns substring of a string from the character with index |
Any NXSL script is built out of a series of statements. A statement can be an assignment, a function call, a loop, a conditional statement or even a statement that does nothing (an empty statement). Statements usually end with a semicolon. In addition, statements can be grouped into a statement-group by encapsulating a group of statements with curly braces. A statement-group is a statement by itself as well. The various statement types are supported:
-
if
-
else
-
while
-
do-while
-
for
-
break
-
continue
-
switch
-
with
-
return
-
exit
The if
construct is one of the most important features of many languages. It allows for conditional execution of code fragments. NXSL features an if
structure that is similar to that of C:
if (expr)
statement
Often you’d want to execute a statement if a certain condition is met, and a
different statement if the condition is not met. This is what else
is for.
else
extends an if
statement to execute a statement in case the
expression in the if
statement evaluates to FALSE
. The else
statement is only executed if the if
expression evaluated to FALSE
.
while
loops are the simplest type of loop in NXSL. They behave just like
their C counterparts. The basic form of a while
statement is:
while (expr)
statement
The meaning of a while
statement is simple. It tells NXSL to execute the
nested statement(s) repeatedly, as long as the while
expression evaluates
to TRUE
. The value of the expression is checked each time at the beginning
of the loop, so even if this value changes during the execution of the nested
statement(s), execution will not stop until the end of the iteration.
do-while
loops are very similar to while
loops, except the truth
expression is checked at the end of each iteration instead of in the beginning.
The main difference from regular while
loops is that the first iteration of
a do-while
loop is guaranteed to run (the truth expression is only checked
at the end of the iteration), whereas it may not necessarily run with a regular
while
loop (the truth expression is checked at the beginning of each
iteration, if it evaluates to FALSE
right from the beginning, the loop
execution would end immediately).
for
loops are the most complex loops in NXSL. They behave in two different ways:
like their C counterparts or in Java way. The syntax of a for
loop is:
for (expr1; expr2; expr3)
statement
for (varName : array)
statement
The first expression (expr1
) is evaluated (executed) once unconditionally
at the beginning of the loop.
In the beginning of each iteration, expr2
is evaluated. If it evaluates to
TRUE
, the loop continues and the nested statement(s) are executed. If it
evaluates to FALSE
, the execution of the loop ends.
At the end of each iteration, expr3
is evaluated (executed).
In the second example for cycle will call statement
for each element in
array. Element will be available as varName
.
continue
is used within looping structures to skip the rest of the current
loop iteration and continue execution at the condition evaluation and then the
beginning of the next iteration.
The switch
statement is similar to a series of if
statements on the
same expression. In many occasions, you may want to compare the same variable
(or expression) with many different values, and execute a different piece of
code depending on which value it equals to. This is exactly what the switch
statement is for.
Example:
switch (input)
{
case "1":
trace(0,"Input is 1");
break;
case "2":
trace(0,"Input is 2");
break;
default:
trace(0, "Input is unknown");
}
The switch
statement also allows to check ranges:
switch (input)
{
case 1:
trace(0,"Input is 1");
break;
case 2:
trace(0,"Input is 2");
break;
case 3...7:
trace(0,"Input is from 3 till 7");
break;
default:
trace(0, "Input is unknown");
}
With statement is made to make the code cleaner and much more readable and to expose variable section to global scope for "Object query" Dashboard element. This statement consists of 2 parts: variable declaration (optional) and expression.
Structure:
with
var = {code},
...
var = {code}
expression
Good Night Simpsons Example for "Object query" Dashboard element. This example will filter out only nodes that are unreachable and will create 2 variables as data providers for columns: time node is down since and oldest alarm time.
with
_down = { return SecondsToUptime(time() - downSince); },
_oldestAlarm = {
oldestAlarmTime = 99999999999;
for (a : $node.alarms) {
oldestAlarmTime = min(oldestAlarmTime, a.creationTime);
}
return strftime("%Y-%m-%d %H:%M", oldestAlarmTime);
}
type == NODE and state & NodeState::Unreachable
//In Object query object attributes are available just using name.
//Like state ($node.state in other scripts)
If called from within a function, the return
statement immediately ends
execution of the current function, and returns its argument as the value of the
function call. Calling return
from main()
function (either explicitly
or implicitly defined) is equivalent of calling exit
.
The simplest yet most accurate way to define an expression is "anything that has a value".
The most basic forms of expressions are constants and variables. When you type
a = 5
, you’re assigning 5
into a
. 5
, obviously, has the value
5, or in other words 5
is an expression with the value of 5 (in this case,
5
is an integer constant).
Slightly more complex examples for expressions are functions. Functions are expressions with the value of their return value.
NXSL supports the following value types: integer values, floating point values (float), string values and arrays. Each of these value types can be assigned into variables or returned from functions.
Another good example of expression orientation is pre- and post-increment and
decrement. You might be familiar with the notation of variable++
and
variable--
. These are increment and decrement operators. In NXSL, like in
C, there are two types of increment - pre-increment and post-increment. Both
pre-increment and post-increment essentially increment the variable, and the
effect on the variable is identical. The difference is with the value of the
increment expression. Pre-increment, which is written ++variable
, evaluates
to the incremented value. Post-increment, which is written variable++
evaluates to the original value of variable, before it was incremented.
A very common type of expressions are comparison expressions. These expressions
evaluate to either FALSE
or TRUE
. NXSL supports >
(bigger than),
>=
(bigger than or equal to), =
(equal), !=
(not equal), <
(less than) and <=
(less than or equal to). These expressions are most
commonly used inside conditional execution, such as if
statements.
The last example of expressions is combined operator-assignment expressions.
You already know that if you want to increment a
by 1, you can simply write
a++
or ++a
. But what if you want to add more than one to it, for
instance 3? In NXSL, adding 3 to the current value of a
can be written a
+= 3
. This means exactly "take the value of a
, add 3 to it, and assign it
back into a
". In addition to being shorter and clearer, this also results
in faster execution. The value of a += 3
, like the value of a regular
assignment, is the assigned value. Notice that it is NOT 3, but the combined
value of a
plus 3 (this is the value that’s assigned into a
). Any
two-place operator can be used in this operator-assignment mode.
Short-circuit evaluation denotes the semantics
of some Boolean operators in which the second argument is only executed or
evaluated if the first argument does not suffice to determine the value of the
expression: when the first argument of the AND function evaluates to false, the
overall value must be false; and when the first argument of the OR function
evaluates to true, the overall value must be true. NXSL uses short-circuit
evaluation for &&
and ||
boolean operators. This feature permits two
useful programming constructs. Firstly, if the first sub-expression checks
whether an expensive computation is needed and the check evaluates to false,
one can eliminate expensive computation in the second argument. Secondly, it
permits a construct where the first expression guarantees a condition without
which the second expression may cause a run-time error. Both are illustrated in
the following example:
if ((x != null) && ((trim(x) == "abc") || (long_running_test(x)))
do_something();
Without short-circuit evaluation, trim(x)
would cause run-time error if
x
is NULL
. Also, long running function will only be called if condition
(trim(x) == "abc"
) will be false.
If run-time error happens during NXSL code execution, the execution will normally stop and error message will be generated.
The try
statement allows to define a block of code to be tested for errors
while it is being executed. Should run-time error occur within that block,
execution of code after the block will continue.
The catch
statement allows to define a block of code to be executed, if an
error occurs in the try
block.
The try
and catch
keywords come in pairs:
try
{
// Block to code to try
}
catch
{
// Block of code to handle errors
}
The following variables with information about the error are avaiable within the
catch
block:
$errorcode |
Error code |
$errorline |
Line number |
$errormodule |
If error happened in a function of script imported using |
$errormsg |
Full error message including error code, line number, error text and, if available, module name. |
$errortext |
Error text |
Since version 3.0, regular expression engine is changed to PCRE (Perl
compatible). Syntax can be checked with pcregrep
, perl itself or on
regex101.com (select PCRE flavour).