2110 lines
61 KiB
ReStructuredText
2110 lines
61 KiB
ReStructuredText
Types
|
|
=====
|
|
|
|
The Zeek scripting language supports the following built-in types:
|
|
|
|
.. list-table::
|
|
:header-rows: 1
|
|
|
|
|
|
* - Name(s)
|
|
- Description
|
|
|
|
* - :zeek:type:`bool`
|
|
- Boolean
|
|
|
|
* - :zeek:type:`count`, :zeek:type:`int`, :zeek:type:`double`
|
|
- Numeric types
|
|
|
|
* - :zeek:type:`time`, :zeek:type:`interval`
|
|
- Time types
|
|
|
|
* - :zeek:type:`string`
|
|
- String
|
|
|
|
* - :zeek:type:`pattern`
|
|
- Regular expression
|
|
|
|
* - :zeek:type:`port`, :zeek:type:`addr`, :zeek:type:`subnet`
|
|
- Network types
|
|
|
|
* - :zeek:type:`enum`
|
|
- Enumeration (user-defined type)
|
|
|
|
* - :zeek:type:`table`, :zeek:type:`set`, :zeek:type:`vector`,
|
|
:zeek:type:`record`
|
|
- Container types
|
|
|
|
* - :zeek:type:`function`, :zeek:type:`event`, :zeek:type:`hook`
|
|
- Executable types
|
|
|
|
* - :zeek:type:`file`
|
|
- File type (only for writing)
|
|
|
|
* - :zeek:type:`opaque`
|
|
- Opaque type (for some built-in functions)
|
|
|
|
* - :zeek:type:`any`
|
|
- Any type (for functions or containers)
|
|
|
|
Here is a more detailed description of each type:
|
|
|
|
|
|
.. zeek:native-type:: addr
|
|
|
|
addr
|
|
----
|
|
|
|
A type representing an IP address.
|
|
|
|
IPv4 address constants are written in "dotted quad" format,
|
|
``A1.A2.A3.A4``, where ``A1``-``A4`` all lie between 0 and 255.
|
|
|
|
IPv6 address constants are written as colon-separated hexadecimal form
|
|
as described by :rfc:`2373` (including the mixed notation with embedded
|
|
IPv4 addresses as dotted-quads in the lower 32 bits), but additionally
|
|
encased in square brackets. Some examples: ``[2001:db8::1]``,
|
|
``[::ffff:192.168.1.100]``, or
|
|
``[aaaa:bbbb:cccc:dddd:eeee:ffff:1111:2222]``.
|
|
|
|
Note that IPv4-mapped IPv6 addresses (i.e., addresses with the first 80
|
|
bits zero, the next 16 bits one, and the remaining 32 bits are the IPv4
|
|
address) are treated internally as IPv4 addresses (for example,
|
|
``[::ffff:192.168.1.100]`` is equal to ``192.168.1.100``).
|
|
|
|
Addresses can be compared for equality (``==``, ``!=``),
|
|
and also for ordering (``<``, ``<=``, ``>``, ``>=``). The absolute value
|
|
of an address gives the size in bits (32 for IPv4, and 128 for IPv6).
|
|
Addresses can also be masked with ``/`` to produce a :zeek:type:`subnet`:
|
|
|
|
.. code-block:: zeek
|
|
|
|
local a: addr = 192.168.1.100;
|
|
local s: subnet = 192.168.0.0/16;
|
|
|
|
if ( a/16 == s )
|
|
print "true";
|
|
|
|
And checked for inclusion within a :zeek:type:`subnet` using ``in``
|
|
or ``!in``:
|
|
|
|
.. code-block:: zeek
|
|
|
|
local a: addr = 192.168.1.100;
|
|
local s: subnet = 192.168.0.0/16;
|
|
|
|
if ( a in s )
|
|
print "true";
|
|
|
|
You can check if a given ``addr`` is IPv4 or IPv6 using
|
|
the :zeek:id:`is_v4_addr` and :zeek:id:`is_v6_addr` built-in functions.
|
|
|
|
Note that hostname constants can also be used, but since a hostname can
|
|
correspond to multiple IP addresses, the type of such a variable is
|
|
``set[addr]``. For example:
|
|
|
|
.. code-block:: zeek
|
|
|
|
local a = www.google.com;
|
|
|
|
Type Conversions
|
|
^^^^^^^^^^^^^^^^
|
|
|
|
.. list-table::
|
|
:header-rows: 1
|
|
|
|
* - To
|
|
- Description
|
|
- Example
|
|
|
|
* - :zeek:see:`string`
|
|
- :zeek:see:`cat` BIF
|
|
- ``cat(foo)``
|
|
|
|
* - :zeek:see:`string`
|
|
- :zeek:see:`fmt` BIF for additional control over the formatting
|
|
- ``fmt("%s", foo)``
|
|
|
|
* - :zeek:see:`subnet`
|
|
- :zeek:see:`addr_to_subnet` BIF
|
|
- ``addr_to_subnet([::1])``
|
|
|
|
|
|
.. zeek:native-type:: any
|
|
|
|
any
|
|
---
|
|
|
|
Used to bypass strong typing. For example, a function can take an
|
|
argument of type ``any`` when it may be of different types.
|
|
The only operation allowed on a variable of type ``any`` is assignment.
|
|
|
|
Note that users aren't expected to use this type. It's provided mainly
|
|
for use by some built-in functions and scripts included with Zeek. For
|
|
example, passing a vector into a ``.bif`` function is best accomplished by
|
|
taking :zeek:type:`any` as an argument and casting it to a vector.
|
|
|
|
|
|
.. zeek:native-type:: bool
|
|
|
|
bool
|
|
----
|
|
|
|
Reflects a value with one of two meanings: true or false. The two
|
|
``bool`` constants are ``T`` and ``F``.
|
|
|
|
The ``bool`` type supports the following operators: equality/inequality
|
|
(``==``, ``!=``), logical and/or (``&&``, ``||``), logical
|
|
negation (``!``), and absolute value (where ``|T|`` is ``1``, and ``|F|`` is
|
|
``0``, and in both cases the result type is :zeek:type:`count`).
|
|
|
|
Type Conversions
|
|
^^^^^^^^^^^^^^^^
|
|
|
|
.. list-table::
|
|
:header-rows: 1
|
|
|
|
* - To
|
|
- Description
|
|
- Example
|
|
|
|
* - :zeek:see:`count`
|
|
- Absolute value operator
|
|
- ``|foo|``
|
|
|
|
* - :zeek:see:`string`
|
|
- :zeek:see:`cat` BIF
|
|
- ``cat(T)``
|
|
|
|
* - :zeek:see:`string`
|
|
- :zeek:see:`fmt` BIF for additional control over the formatting
|
|
- ``fmt("%s", F)``
|
|
|
|
|
|
.. zeek:native-type:: count
|
|
|
|
count
|
|
-----
|
|
|
|
A numeric type representing a 64-bit unsigned integer. A ``count``
|
|
constant is a string of digits, e.g. ``1234`` or ``0``. A ``count``
|
|
can also be written in hexadecimal notation (in which case ``0x`` must
|
|
precede the hex digits), e.g. ``0xff`` or ``0xABC123``.
|
|
|
|
The ``count`` type supports the same operators as the :zeek:type:`int`
|
|
type, but a unary plus or minus applied to a ``count`` results in an
|
|
:zeek:type:`int`.
|
|
|
|
In addition, ``count`` types support more bitwise operations. You can use
|
|
``&``, ``|``, ``^``, ``<<``, and ``>>`` for bitwise ``and``, ``or``,
|
|
``xor``, ``left shift``, and ``right shift``. You can also use ``~``
|
|
for bitwise (one's) complement.
|
|
|
|
For unsigned arithmetic involving ``count`` types that cause overflows
|
|
(results that exceed the numeric limits of representable value in either
|
|
direction), Zeek's behavior is to wrap the result modulo 2^64 back into
|
|
the range of representable values (the same behavior as defined by C++).
|
|
|
|
.. note::
|
|
|
|
Integer literals in Zeek that are not preceded by a unary ``+`` or ``-``
|
|
are treated as the unsigned ``count`` type. This can cause unintentional
|
|
surprises is some situations, like for an absolute-value operation of
|
|
``|5 - 9|`` that results in an unsigned-integer overflow to the large number
|
|
of ``18446744073709551612`` where ``|+5 - +9|`` results in signed-integer
|
|
arithmetic and (likely) more expected result of ``4``.
|
|
|
|
Type Conversions
|
|
^^^^^^^^^^^^^^^^
|
|
|
|
.. list-table::
|
|
:header-rows: 1
|
|
|
|
* - To
|
|
- Description
|
|
- Example
|
|
|
|
* - :zeek:see:`addr`
|
|
- :zeek:see:`count_to_v4_addr` BIF
|
|
- ``count_to_v4_addr(2130706433)``
|
|
|
|
* - :zeek:see:`bool`
|
|
- Relational operator
|
|
- ``foo > 0``
|
|
|
|
* - :zeek:see:`double`
|
|
- :zeek:see:`count_to_double` BIF
|
|
- ``count_to_double(42)``
|
|
|
|
* - :zeek:see:`double`
|
|
- Addition operator
|
|
- ``foo + 0.0``
|
|
|
|
* - :zeek:see:`double`
|
|
- Division operator
|
|
- ``foo / 1.0``
|
|
|
|
* - :zeek:see:`double`
|
|
- Multiplication operator
|
|
- ``foo * 1.0``
|
|
|
|
* - :zeek:see:`double`
|
|
- Subtraction operator
|
|
- ``foo - 0.0``
|
|
|
|
* - :zeek:see:`port`
|
|
- :zeek:see:`count_to_port` BIF
|
|
- ``count_to_port(80, tcp)``
|
|
|
|
* - :zeek:see:`string`
|
|
- :zeek:see:`cat` BIF
|
|
- ``cat(foo)``
|
|
|
|
* - :zeek:see:`string`
|
|
- :zeek:see:`fmt` BIF for additional control over the formatting
|
|
- ``fmt("%x", 3735928559)``
|
|
|
|
|
|
.. zeek:native-type:: double
|
|
|
|
double
|
|
------
|
|
|
|
A numeric type representing a double-precision floating-point
|
|
number. Floating-point constants are written as a string of digits
|
|
with an optional decimal point, optional scale-factor in scientific
|
|
notation, and optional ``+`` or ``-`` sign. Examples are ``-1234``,
|
|
``-1234e0``, ``3.14159``, and ``.003E-23``.
|
|
|
|
The ``double`` type supports the following operators: arithmetic
|
|
operators (``+``, ``-``, ``*``, ``/``), comparison operators
|
|
(``==``, ``!=``, ``<``, ``<=``, ``>``, ``>=``), assignment operators
|
|
(``=``, ``+=``, ``-=``), unary plus and minus (``+``, ``-``), and
|
|
absolute value (e.g., ``|-3.14|`` is 3.14).
|
|
|
|
When using type inferencing use care so that the
|
|
intended type is inferred, e.g. ``local size_difference = 5`` will
|
|
infer :zeek:type:`count`, while ``local size_difference = 5.0``
|
|
will infer ``double``.
|
|
|
|
Type Conversions
|
|
^^^^^^^^^^^^^^^^
|
|
|
|
.. list-table::
|
|
:header-rows: 1
|
|
|
|
* - To
|
|
- Description
|
|
- Example
|
|
|
|
* - :zeek:see:`count`
|
|
- :zeek:see:`double_to_count` BIF
|
|
- ``double_to_count(1234.0)``
|
|
|
|
* - :zeek:see:`interval`
|
|
- :zeek:see:`double_to_interval` BIF
|
|
- ``double_to_interval(86400.0)``
|
|
|
|
* - :zeek:see:`time`
|
|
- :zeek:see:`double_to_time` BIF
|
|
- ``double_to_time(1626723410.4)``
|
|
|
|
* - :zeek:see:`string`
|
|
- :zeek:see:`cat` BIF
|
|
- ``cat(foo)``
|
|
|
|
* - :zeek:see:`string`
|
|
- :zeek:see:`fmt` BIF for additional control over the formatting
|
|
- ``fmt("%.2f", 3.14159265)``
|
|
|
|
|
|
.. zeek:native-type:: enum
|
|
|
|
enum
|
|
----
|
|
|
|
A type allowing the specification of a set of related values that
|
|
have no further structure. An example declaration:
|
|
|
|
.. code-block:: zeek
|
|
|
|
type color: enum { Red, White, Blue, };
|
|
|
|
The last comma after ``Blue`` is optional. Both the type name ``color``
|
|
and the individual values (``Red``, etc. -- not ``color::Red``) have
|
|
global scope.
|
|
|
|
Enumerations may assign :zeek:type:`count` values explicitly:
|
|
|
|
.. code-block:: zeek
|
|
|
|
type color: enum { Red = 10, White = 20, Blue = 30 };
|
|
|
|
Without explicit assignment, Zeek numbers enumerations sequentially starting
|
|
from 0. You may not mix explicit and implicit assignments.
|
|
|
|
The only operations allowed on enumerations are equality comparisons (``==``,
|
|
``!=``) and assignment (``=``). Enumerations do not automatically yield their
|
|
values or provide ordering (neither ``Red == 10`` nor ``Red < White`` works),
|
|
but the :zeek:see:`enum_to_int` BIF lets you retrieve an enumeration's numeric
|
|
value if you require such logic.
|
|
|
|
.. note::
|
|
|
|
We recommend using explicit value assignment when relying on numeric values,
|
|
since it avoids sensitivity to :zeek:keyword:`@load` sequencing when
|
|
enumerations are :zeek:keyword:`redef`'d in multiple scripts.
|
|
|
|
Type Conversions
|
|
^^^^^^^^^^^^^^^^
|
|
|
|
.. list-table::
|
|
:header-rows: 1
|
|
|
|
* - To
|
|
- Description
|
|
- Example
|
|
|
|
* - :zeek:see:`int`
|
|
- :zeek:see:`enum_to_int` BIF
|
|
- ``enum_to_int(Intel::ADDR)``
|
|
|
|
* - :zeek:see:`int`
|
|
- Absolute value operator
|
|
- ``|Intel::ADDR|``
|
|
|
|
* - :zeek:see:`string`
|
|
- :zeek:see:`cat` BIF
|
|
- ``cat(foo)``
|
|
|
|
* - :zeek:see:`string`
|
|
- :zeek:see:`fmt` BIF for additional control over the formatting
|
|
- ``fmt("%s", foo)``
|
|
|
|
|
|
.. zeek:native-type:: event
|
|
|
|
event
|
|
-----
|
|
|
|
Event handlers are nearly identical in both syntax and semantics to
|
|
a :zeek:type:`function`, with the two differences being that event
|
|
handlers have no return type since they never return a value, and
|
|
you cannot call an event handler.
|
|
|
|
Example:
|
|
|
|
.. code-block:: zeek
|
|
|
|
event my_event(r: bool, s: string)
|
|
{
|
|
print "my_event", r, s;
|
|
}
|
|
|
|
Instead of directly calling an event handler from a script, event
|
|
handler bodies are executed when they are invoked by one of three
|
|
different methods:
|
|
|
|
- From the event engine
|
|
|
|
When the event engine detects an event for which you have
|
|
defined a corresponding event handler, it queues an event for
|
|
that handler. The handler is invoked as soon as the event
|
|
engine finishes processing the current packet and flushing the
|
|
invocation of other event handlers that were queued first.
|
|
|
|
- With the ``event`` statement from a script
|
|
|
|
Immediately queuing invocation of an event handler occurs like:
|
|
|
|
.. code-block:: zeek
|
|
|
|
event password_exposed(user, password);
|
|
|
|
This assumes that ``password_exposed`` was previously declared
|
|
as an event handler type with compatible arguments.
|
|
|
|
- Via the :zeek:keyword:`schedule` expression in a script
|
|
|
|
This delays the invocation of event handlers until some time in
|
|
the future. For example:
|
|
|
|
.. code-block:: zeek
|
|
|
|
schedule 5 secs { password_exposed(user, password) };
|
|
|
|
Multiple event handler bodies can be defined for the same event handler
|
|
identifier and the body of each will be executed in turn. Ordering
|
|
of their execution can be influenced with :zeek:attr:`&priority`.
|
|
|
|
Multiple alternate event prototype declarations are allowed, but the
|
|
alternates must be some subset of the first, canonical prototype and
|
|
arguments must match by name and type. This allows users to define
|
|
handlers for any such prototype they may find convenient or for the core
|
|
set of handlers to be extended, changed, or deprecated without breaking
|
|
existing handlers a user may have written. Example:
|
|
|
|
.. code-block:: zeek
|
|
|
|
# Event Prototype Declarations
|
|
global my_event: event(s: string, c: count);
|
|
global my_event: event(c: count);
|
|
global my_event: event();
|
|
|
|
# Event Handler Definitions
|
|
event my_event(s: string, c: count)
|
|
{
|
|
print "my event", s, c;
|
|
}
|
|
|
|
event my_event(c: count)
|
|
{
|
|
print "my event", c;
|
|
}
|
|
|
|
event my_event()
|
|
{
|
|
print "my event";
|
|
}
|
|
|
|
By using alternate event prototypes, handlers are allowed to consume a
|
|
subset of the full argument list as given by the first prototype
|
|
declaration. It also even allows arguments to be ordered differently
|
|
from the canonical prototype.
|
|
|
|
To use :zeek:attr:`&default` on event arguments, it must appear on the
|
|
first, canonical prototype.
|
|
|
|
Employing its static analysis capabilities, Zeek will warn if it cannot
|
|
determine that an event will ever be triggered. In case the warning is not
|
|
appropriate (e.g., the event might be triggered remotely via broker),
|
|
:zeek:attr:`&is_used` can be applied to suppress the warning.
|
|
|
|
|
|
.. zeek:native-type:: file
|
|
|
|
file
|
|
----
|
|
|
|
Zeek supports writing to files, but not reading from them (to read from
|
|
files see the :doc:`/frameworks/input`). Files
|
|
can be opened using either the :zeek:id:`open` or :zeek:id:`open_for_append`
|
|
built-in functions, and closed using the :zeek:id:`close` built-in
|
|
function. For example, declare, open, and write to a file and finally
|
|
close it like:
|
|
|
|
.. code-block:: zeek
|
|
|
|
local f = open("myfile");
|
|
print f, "hello, world";
|
|
close(f);
|
|
|
|
Writing to files like this for logging usually isn't recommended, for better
|
|
logging support see :doc:`/frameworks/logging`.
|
|
|
|
|
|
.. zeek:native-type:: function
|
|
|
|
function
|
|
--------
|
|
|
|
Function types in Zeek are declared using::
|
|
|
|
function( argument* ): type
|
|
|
|
where ``argument*`` is a (possibly empty) comma-separated list of
|
|
arguments, and ``type`` is an optional return type. For example:
|
|
|
|
.. code-block:: zeek
|
|
|
|
global greeting: function(name: string): string;
|
|
|
|
Here ``greeting`` is an identifier with a certain function type.
|
|
The function body is not defined yet and ``greeting`` could even
|
|
have different function body values at different times. To define
|
|
a function including a body value, the syntax is like:
|
|
|
|
.. code-block:: zeek
|
|
|
|
function greeting(name: string): string
|
|
{
|
|
return "Hello, " + name;
|
|
}
|
|
|
|
Note that in the definition above, it's not necessary for us to have
|
|
done the first (forward) declaration of ``greeting`` as a function
|
|
type, but when it is, the return type and argument list (including the
|
|
name of each argument) must match exactly.
|
|
|
|
Here is an example function that takes no parameters and does not
|
|
return a value:
|
|
|
|
.. code-block:: zeek
|
|
|
|
function my_func()
|
|
{
|
|
print "my_func";
|
|
}
|
|
|
|
Function types don't need to have a name and can be assigned anonymously:
|
|
|
|
.. code-block:: zeek
|
|
|
|
greeting = function(name: string): string { return "Hi, " + name; };
|
|
|
|
And finally, the function can be called like:
|
|
|
|
.. code-block:: zeek
|
|
|
|
print greeting("Dave");
|
|
|
|
.. _anonymous-function:
|
|
|
|
Anonymous functions and their closures
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
Anonymously defined functions (lambdas) capture their closures. This means
|
|
that they can use variables from their enclosing scope at the time of their
|
|
creation. In older-style deprecated functionality (capture by "reference"),
|
|
closure-capture happens automatically. The current style
|
|
(capture by "copy") requires explicitly listing the captured variables.
|
|
|
|
Here is an example of a simple anonymous function that automatically
|
|
captures its closure in Zeek (deprecated functionality):
|
|
|
|
.. code-block:: zeek
|
|
|
|
local make_adder = function(n: count): function(m: count): count
|
|
{
|
|
return function (m: count): count
|
|
{
|
|
return n + m;
|
|
};
|
|
};
|
|
|
|
print make_adder(3)(5); # prints 8
|
|
|
|
local three = make_adder(3);
|
|
print three(5); # prints 8
|
|
|
|
Here ``make_adder`` is generating a function that captures ``n`` in its
|
|
closure. The same, but in current (non-deprecated, closure-by-copy) form:
|
|
|
|
.. code-block:: zeek
|
|
|
|
local make_adder = function(n: count): function(m: count): count
|
|
{
|
|
return function [n] (m: count): count
|
|
{
|
|
return n + m;
|
|
};
|
|
};
|
|
|
|
print make_adder(3)(5); # prints 8
|
|
|
|
local three = make_adder(3);
|
|
print three(5); # prints 8
|
|
|
|
The only difference is that the inner anonymous function explicitly declares
|
|
that ``n`` is captured, by listing all of the captured variables in ``[...]``
|
|
after the :zeek:type:`function` keyword. It is a compile-time error to fail to
|
|
list a captured variable (or to list the same variable more than once, or to
|
|
list a global variable).
|
|
|
|
Old-style capture-by-reference closure semantics means that those
|
|
anonymous functions can modify the variables in their closures. For example:
|
|
|
|
.. code-block:: zeek
|
|
|
|
local n = 3;
|
|
local f = function() { n += 1; print n; };
|
|
f(); # prints 4
|
|
print n; # prints 4
|
|
n = 0;
|
|
f(); # prints 1, since n is shared between outer and inner functions
|
|
print n; # prints 1
|
|
|
|
The same in capture-by-copy, however, yields different results:
|
|
|
|
.. code-block:: zeek
|
|
|
|
local n = 3;
|
|
local f = function [n] () { n += 1; print n; };
|
|
f(); # prints 4
|
|
print n; # prints 3, since n is not shared
|
|
n = 0;
|
|
f(); # prints 5, since n persists for f
|
|
print n; # prints 0
|
|
|
|
With capture-by-copy, by default variables are captured using the equivalent
|
|
of ``=`` assignments. In Zeek, variable assignments use "shallow" copy,
|
|
meaning that assignments of aggregates share the same aggregate rather
|
|
than fully duplicating all of its members. These semantics allow you to
|
|
get the equivalent of the original "reference" semantics by using record
|
|
fields rather than variables for the sharing. For example:
|
|
|
|
.. code-block:: zeek
|
|
|
|
type r: record { n: count; };
|
|
...
|
|
local var = r($n=3);
|
|
local f = function [var] () { var$n += 1; print var$n; };
|
|
f(); # prints 4
|
|
print var$n; # prints 4
|
|
var$n = 0;
|
|
f(); # prints 1, since n is shared between outer and inner functions
|
|
print var$n; # prints 1
|
|
|
|
You can specify that a given variable should instead be captured using
|
|
a *deep* copy by preceding it with the ``copy`` keyword:
|
|
|
|
.. code-block:: zeek
|
|
|
|
type r: record { n: count; };
|
|
...
|
|
local var = r($n=3);
|
|
local f = function [copy var] () { var$n += 1; print var$n; };
|
|
f(); # prints 4
|
|
print var$n; # prints 3, since the var aggregate is not shared
|
|
var$n = 0;
|
|
f(); # prints 5, since the function has its own deep copy of var
|
|
print var$n; # prints 0
|
|
|
|
Finally, you can intermingle both shallow and deep copying, as shown in
|
|
this fragment:
|
|
|
|
.. code-block:: zeek
|
|
|
|
type r: record { n: count; };
|
|
...
|
|
local var1 = r($n=3);
|
|
local var2 = r($n=7);
|
|
local f = function [copy var1, var2] () { ...
|
|
|
|
where ``var1`` will be captured via deep-copy and ``var2`` via the normal
|
|
shallow-copy.
|
|
|
|
When anonymous functions are serialized over Broker they keep their closures,
|
|
but they will not continue to mutate the values from the sending script (either
|
|
directly, for reference semantics, or for shallow-copy aggregates, for copy
|
|
semantics). At the time of serialization they create a copy of their closure.
|
|
Also, anonymous functions do not capture global variables in their closures and
|
|
thus will use the receiver's global variables.
|
|
|
|
In order to serialize an anonymous function, that function must have been
|
|
already declared on the receiver's end, because Zeek does not serialize the
|
|
function's source code. See :file:`testing/btest/language/closure-sending.zeek`
|
|
for an example of how to serialize anonymous functions over Broker.
|
|
|
|
.. _default-values:
|
|
|
|
Default values
|
|
^^^^^^^^^^^^^^
|
|
|
|
Function parameters may specify default values as long as they appear
|
|
last in the parameter list:
|
|
|
|
.. code-block:: zeek
|
|
|
|
global foo: function(s: string, t: string &default="abc", u: count &default=0);
|
|
|
|
If a function was previously declared with default parameters, the
|
|
default expressions can be omitted when implementing the function
|
|
body and they will still be used for function calls that lack those
|
|
arguments.
|
|
|
|
.. code-block:: zeek
|
|
|
|
function foo(s: string, t: string, u: count)
|
|
{
|
|
print s, t, u;
|
|
}
|
|
|
|
And calls to the function may omit the defaults from the argument list:
|
|
|
|
.. code-block:: zeek
|
|
|
|
foo("test");
|
|
|
|
Asynchronous functions
|
|
^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
Use of the ``return when`` construct renders a function *asynchronous*: it
|
|
will return its result at a later time, when an underlying condition becomes
|
|
fulfilled. See :zeek:keyword:`when` and the description of :ref:`asynchronous
|
|
returns <asynchronous-return>` for details.
|
|
|
|
|
|
.. zeek:native-type:: hook
|
|
|
|
hook
|
|
----
|
|
|
|
A hook is another flavor of function that shares characteristics of
|
|
both a :zeek:type:`function` and an :zeek:type:`event`. They are like
|
|
events in that many handler bodies can be defined for the same hook
|
|
identifier and the order of execution can be enforced with
|
|
:zeek:attr:`&priority`. They are more like functions in the way they
|
|
are invoked/called, because, unlike events, their execution is
|
|
immediate and they do not get scheduled through an event queue.
|
|
Also, a unique feature of a hook is that a given hook handler body
|
|
can short-circuit the execution of remaining hook handlers simply by
|
|
exiting from the body as a result of a :zeek:keyword:`break` statement (as
|
|
opposed to a :zeek:keyword:`return` or just reaching the end of the body).
|
|
|
|
A hook type is declared like::
|
|
|
|
hook( argument* )
|
|
|
|
where ``argument*`` is a (possibly empty) comma-separated list of
|
|
arguments. For example:
|
|
|
|
.. code-block:: zeek
|
|
|
|
global myhook: hook(s: string, vs: vector of string);
|
|
|
|
Here ``myhook`` is the hook type identifier and no hook handler
|
|
bodies have been defined for it yet. To define some hook handler
|
|
bodies the syntax looks like:
|
|
|
|
.. code-block:: zeek
|
|
|
|
hook myhook(s: string, vs: vector of string) &priority=10
|
|
{
|
|
print "priority 10 myhook handler", s, vs;
|
|
s = "bye";
|
|
vs += "modified";
|
|
}
|
|
|
|
hook myhook(s: string, vs: vector of string)
|
|
{
|
|
print "break out of myhook handling", s, vs;
|
|
break;
|
|
}
|
|
|
|
hook myhook(s: string, vs: vector of string) &priority=-5
|
|
{
|
|
print "not going to happen", s, vs;
|
|
}
|
|
|
|
Note that the first (forward) declaration of ``myhook`` as a hook
|
|
type isn't strictly required. Argument types must match for all
|
|
hook handlers and any forward declaration of a given hook.
|
|
|
|
To invoke immediate execution of all hook handler bodies, they
|
|
are called similarly to a function, except preceded by the ``hook``
|
|
keyword:
|
|
|
|
.. code-block:: zeek
|
|
|
|
hook myhook("hi", vector("foo"));
|
|
|
|
or
|
|
|
|
.. code-block:: zeek
|
|
|
|
if ( hook myhook("hi", vector("foo")) )
|
|
print "all handlers ran";
|
|
|
|
And the output would look like::
|
|
|
|
priority 10 myhook handler, hi, [foo]
|
|
break out of myhook handling, hi, [foo, modified]
|
|
|
|
Note how the re-assigning of a ``hook`` argument (``s = "bye"`` in the example)
|
|
will not be visible to remaining ``hook`` handlers, but it's still possible
|
|
to modify values of composite/aggregate types like :zeek:type:`vector`,
|
|
:zeek:type:`record`, :zeek:type:`set`, or :zeek:type:`table`.
|
|
|
|
The return value of a hook call is an implicit :zeek:type:`bool`
|
|
value with ``T`` meaning that all handlers for the hook were
|
|
executed and ``F`` meaning that only some of the handlers may have
|
|
executed due to one handler body exiting as a result of a ``break``
|
|
statement.
|
|
|
|
Hooks are also allowed to have multiple/alternate prototype declarations,
|
|
just like an :zeek:see:`event`.
|
|
|
|
|
|
.. zeek:native-type:: int
|
|
|
|
int
|
|
---
|
|
|
|
A numeric type representing a 64-bit signed integer. An ``int`` constant
|
|
is a string of digits preceded by a ``+`` or ``-`` sign, e.g.
|
|
``-42`` or ``+5`` (the ``+`` sign is optional but see note about type
|
|
inferencing below). An ``int`` constant can also be written in
|
|
hexadecimal notation (in which case ``0x`` must be between the sign and
|
|
the hex digits), e.g. ``-0xFF`` or ``+0xabc123``.
|
|
|
|
The ``int`` type supports the following operators: arithmetic
|
|
operators (``+``, ``-``, ``*``, ``/``, ``%``), comparison operators
|
|
(``==``, ``!=``, ``<``, ``<=``, ``>``, ``>=``), assignment operators
|
|
(``=``, ``+=``, ``-=``), pre-increment (``++``), pre-decrement
|
|
(``--``), unary plus and minus (``+``, ``-``), absolute value
|
|
(e.g., ``|-3|`` is 3, but the result type is :zeek:type:`count`), and
|
|
bitwise shift operations (``<<``, ``>>``).
|
|
|
|
When using type inferencing, use care so that the
|
|
intended type is inferred, e.g. ``local size_difference = 0`` will
|
|
infer :zeek:type:`count`, while ``local size_difference = +0``
|
|
will infer ``int``.
|
|
|
|
For signed-integer arithmetic involving ``int`` types that cause overflows
|
|
(results that exceed the numeric limits of representable values in either
|
|
direction), Zeek's behavior is generally undefined and one should not rely on
|
|
any observed behavior being consistent across compilers, platforms, time, etc.
|
|
The reason for this is that the C++ standard also deems this as undefined
|
|
behavior and Zeek does not currently attempt to detect such overflows within
|
|
its underlying C++ implementation (some limited cases may try to statically
|
|
determine at parse-time that an overflow will definitely occur and reject them
|
|
an error, but don't rely on that).
|
|
|
|
Type Conversions
|
|
^^^^^^^^^^^^^^^^
|
|
|
|
.. list-table::
|
|
:header-rows: 1
|
|
|
|
* - To
|
|
- Description
|
|
- Example
|
|
|
|
* - :zeek:see:`bool`
|
|
- Relational operator
|
|
- ``foo != 0``
|
|
|
|
* - :zeek:see:`count`
|
|
- Absolute value operator
|
|
- ``|foo|``
|
|
|
|
* - :zeek:see:`count`
|
|
- :zeek:see:`int_to_count` BIF
|
|
- ``int_to_count(42)``
|
|
|
|
* - :zeek:see:`double`
|
|
- :zeek:see:`int_to_double` BIF
|
|
- ``int_to_double(foo)``
|
|
|
|
* - :zeek:see:`double`
|
|
- Addition operator
|
|
- ``foo + 0.0``
|
|
|
|
* - :zeek:see:`double`
|
|
- Division operator
|
|
- ``foo / 1.0``
|
|
|
|
* - :zeek:see:`double`
|
|
- Multiplication operator
|
|
- ``foo * 1.0``
|
|
|
|
* - :zeek:see:`string`
|
|
- :zeek:see:`cat` BIF
|
|
- ``cat(-10)``
|
|
|
|
* - :zeek:see:`string`
|
|
- :zeek:see:`fmt` BIF for additional control over the formatting
|
|
- ``fmt("%s", 0)``
|
|
|
|
|
|
.. zeek:native-type:: interval
|
|
|
|
interval
|
|
--------
|
|
|
|
A temporal type representing a relative time. An ``interval``
|
|
constant can be written as a numeric constant followed by a time
|
|
unit where the time unit is one of ``usec``, ``msec``, ``sec``, ``min``,
|
|
``hr``, or ``day`` which respectively represent microseconds, milliseconds,
|
|
seconds, minutes, hours, and days. Whitespace between the numeric
|
|
constant and time unit is optional. Appending the letter ``s`` to the
|
|
time unit in order to pluralize it is also optional (to no semantic
|
|
effect). Examples of ``interval`` constants are ``3.5 min`` and
|
|
``3.5mins``. An ``interval`` can also be negated, for example
|
|
``-12 hr`` represents "twelve hours in the past".
|
|
|
|
Intervals support addition and subtraction, the comparison operators
|
|
(``==``, ``!=``, ``<``, ``<=``, ``>``, ``>=``), the assignment
|
|
operators (``=``, ``+=``, ``-=``), and unary plus and minus (``+``, ``-``).
|
|
|
|
Intervals also support division (in which case the result is a
|
|
:zeek:type:`double` value). An ``interval`` can be multiplied or divided
|
|
by an arithmetic type (``count``, ``int``, or ``double``) to produce
|
|
an ``interval`` value. The absolute value of an ``interval`` is a
|
|
``double`` value equal to the number of seconds in the ``interval``
|
|
(e.g., ``|-1 min|`` is 60.0).
|
|
|
|
Type Conversions
|
|
^^^^^^^^^^^^^^^^
|
|
|
|
.. list-table::
|
|
:header-rows: 1
|
|
|
|
* - To
|
|
- Description
|
|
- Example
|
|
|
|
* - :zeek:see:`double`
|
|
- :zeek:see:`interval_to_double` BIF
|
|
- ``interval_to_double(5mins)``
|
|
|
|
* - :zeek:see:`double`
|
|
- Absolute value operator
|
|
- ``|foo|``
|
|
|
|
* - :zeek:see:`string`
|
|
- :zeek:see:`cat` BIF
|
|
- ``cat(foo)``
|
|
|
|
* - :zeek:see:`string`
|
|
- :zeek:see:`fmt` BIF for additional control over the formatting
|
|
- ``fmt("%s", foo)``
|
|
|
|
* - :zeek:see:`time`
|
|
- Addition operator
|
|
- ``5 mins + start_time``
|
|
|
|
* - :zeek:see:`time`
|
|
- Subtraction operator
|
|
- ``start_time - 60 secs``
|
|
|
|
|
|
.. zeek:native-type:: opaque
|
|
|
|
opaque
|
|
------
|
|
|
|
A data type whose actual representation/implementation is
|
|
intentionally hidden, but whose values may be passed to certain
|
|
built-in functions that can actually access the internal/hidden resources.
|
|
Opaque types are differentiated from each other by qualifying them
|
|
like ``opaque of md5`` or ``opaque of sha1``.
|
|
|
|
An example use of this type is the set of built-in functions which
|
|
perform hashing:
|
|
|
|
.. code-block:: zeek
|
|
|
|
local handle = md5_hash_init();
|
|
# Explicitly -> local handle : opaque of md5 = ...
|
|
md5_hash_update(handle, "test");
|
|
md5_hash_update(handle, "testing");
|
|
print md5_hash_finish(handle);
|
|
|
|
Here the opaque type is used to provide a handle to a particular
|
|
resource which is calculating an MD5 hash incrementally over
|
|
time, but the details of that resource aren't relevant, it's only
|
|
necessary to have a handle as a way of identifying it and
|
|
distinguishing it from other such resources.
|
|
|
|
The scripting layer implementations of these types are found primarily in
|
|
:doc:`/scripts/base/bif/zeek.bif.zeek` and a more granular look at them
|
|
can be found in ``src/OpaqueVal.h/cc`` inside the Zeek repo. Opaque types
|
|
are a good way to integrate functionality into Zeek without needing to
|
|
add an entire new type to the scripting language.
|
|
|
|
.. zeek:type:: paraglob
|
|
|
|
An opaque type for creating and using paraglob data structures inside of
|
|
Zeek. A paraglob is a data structure for fast string matching against a
|
|
large set of glob style patterns. It can be loaded with a vector of
|
|
patterns, and then queried with input strings. Note that these patterns are
|
|
just strings, and not the pattern type built in to Zeek. For a query it
|
|
returns all of the patterns that it contains matching that input string.
|
|
|
|
Paraglobs offer significant performance advantages over making a pass over
|
|
a vector of patterns and checking each one. Note though that initializing a
|
|
paraglob can take some time for very large pattern sets (1,000,000+
|
|
patterns) and care should be taken to only initialize one with a large
|
|
pattern set when there is time for the paraglob to compile. Subsequent get
|
|
operations run very quickly though, even for very large pattern sets.
|
|
|
|
.. code-block:: zeek
|
|
|
|
local v = vector("*", "d?g", "*og", "d?", "d[!wl]g");
|
|
local p : opaque of paraglob = paraglob_init(v);
|
|
print paraglob_match(p, "dog");
|
|
# out: [*, *og, d?g, d[!wl]g]
|
|
|
|
For more documentation on paraglob see :doc:`/components/index`.
|
|
|
|
.. zeek:see:: md5_hash_init sha1_hash_init sha256_hash_init
|
|
hll_cardinality_add bloomfilter_basic_init
|
|
|
|
|
|
.. zeek:native-type:: pattern
|
|
|
|
pattern
|
|
-------
|
|
|
|
A type representing regular-expression patterns that can be used for fast
|
|
text-searching operations. Pattern constants are created by enclosing text
|
|
within forward slashes (``/``) and support a large subset of the `flex lexical
|
|
analyzer <http://westes.github.io/flex/manual/Patterns.html>`_ syntax. As in
|
|
other implementations, patterns consist of ordinary and special characters.
|
|
Patterns such as ``/a/`` or ``/A0123/`` match that specific character byte or
|
|
character sequence, case-sensitively. Special characters and modifiers customize
|
|
matching, as follows:
|
|
|
|
.. list-table::
|
|
:header-rows: 1
|
|
|
|
* - Syntax
|
|
- Meaning
|
|
|
|
* - ``^``
|
|
- Matches the beginning of the input.
|
|
|
|
* - ``$``
|
|
- Matches the end of the input.
|
|
|
|
* - ``.``
|
|
- Matches any character except newline (but see the ``(?s:`` and ``/s`` modifiers).
|
|
|
|
* - ``<expr>*``
|
|
- Matches zero or more instances of ``expr``.
|
|
|
|
* - ``<expr>+``
|
|
- Matches one or more instances of ``expr``.
|
|
|
|
* - ``<expr>?``
|
|
- Matches zero or one instance of ``expr``.
|
|
|
|
* - ``<expr>{n}``
|
|
- Matches ``expr`` ``n`` times, where ``n`` is a non-negative integer.
|
|
|
|
* - ``<expr>{n,}``
|
|
- Matches ``expr`` ``n`` or more times, where ``n`` is a non-negative integer.
|
|
|
|
* - ``<expr>{n,m}``
|
|
- Matches ``expr`` between ``n`` and ``m`` times, inclusively, where ``n``
|
|
and ``m`` are non-negative integers and ``m >= n``.
|
|
|
|
* - ``<expr1>|<expr2>``
|
|
- Matches either ``expr1`` or ``expr2``.
|
|
|
|
* - ``(<expr>)``
|
|
- Groups the contained expression to form a building-block of a more complex
|
|
one.
|
|
|
|
* - ``"<chars>"``
|
|
- Matches literal strings, without the quotation marks. These always match
|
|
as given, even if case-insensitivity is active.
|
|
|
|
* - ``[<chars>]``
|
|
- Defines a character class, matching any of the contained characters.
|
|
|
|
* - ``[^<chars>]``
|
|
- Defines a negated character class, matching any but the contained
|
|
characters.
|
|
|
|
* - ``<char1>-<char2>``
|
|
- Inside a character class this specifies a range, matching any character
|
|
between ``<char1>`` and ``<char2>``, inclusively. Outside a character
|
|
class it matches the literal string.
|
|
|
|
* - ``(?i:<expr>)``
|
|
- Matches the expression case-insensitively.
|
|
|
|
* - ``(?s:<expr>)``
|
|
- Treats the input as a single line: the ``.`` character also matches
|
|
newlines.
|
|
|
|
Zeek supports the following pre-defined character classes:
|
|
|
|
.. list-table::
|
|
:header-rows: 1
|
|
:widths: 20 20 60
|
|
|
|
* - Shorthand
|
|
- Equivalent to
|
|
- Meaning
|
|
|
|
* - ``[:alnum:]``
|
|
- ``[A-Za-z0-9]``
|
|
- Upper- and lowercase letters plus digits.
|
|
|
|
* - ``[:alpha:]``
|
|
- ``[A-Za-z]``
|
|
- Upper- and lowercase letters.
|
|
|
|
* - ``[:blank:]``
|
|
- ``[ \t]``
|
|
- The space or tab character.
|
|
|
|
* - ``[:cntrl:]``
|
|
-
|
|
- Non-printable characters, a.k.a. control characters. See
|
|
`iscntrl() <https://cplusplus.com/reference/cctype/iscntrl/>`_ for details.
|
|
|
|
* - ``[:digit:]``
|
|
- ``[0-9]``
|
|
- Digits.
|
|
|
|
* - ``[:graph:]``
|
|
- ``[^ [:cntrl:]]``
|
|
- Characters with graphic representation: everything other than space
|
|
and control characters.
|
|
|
|
* - ``[:print:]``
|
|
- ``[^[:cntrl:]]``
|
|
- Printable characters: those with graphic representation, plus the space character.
|
|
|
|
* - ``[:punct:]``
|
|
-
|
|
- Punctuation: any characters with graphic representation that are not alphanumeric.
|
|
|
|
* - ``[:space:]``
|
|
- ``[ \t\n\r\f\v]``
|
|
- Whitespace characters.
|
|
|
|
* - ``[:xdigit:]``
|
|
- ``[A-Fa-f0-9]``
|
|
- Hexadecimal characters.
|
|
|
|
* - ``[:lower:]``
|
|
- ``[a-z]``
|
|
- Lowercase letters.
|
|
|
|
* - ``[:upper:]``
|
|
- ``[A-Z]``
|
|
- Uppercase letters.
|
|
|
|
To match special characters, escape them with a backslash (``\``).
|
|
|
|
Zeek also supports the following pattern-level operators and modifiers:
|
|
|
|
.. list-table::
|
|
:header-rows: 1
|
|
|
|
* - Example
|
|
- Meaning
|
|
|
|
* - ``/<expr1>/ | /<expr2>/``
|
|
- Succeeds when either pattern matches the input.
|
|
|
|
* - ``/<expr1>/ & /<expr2>/``
|
|
- Succeeds when the concatenation of both patterns matches the input. Note
|
|
that this differs from a logical "AND"; ordering matters.
|
|
|
|
* - ``/<expr>/i``
|
|
- Matches the expression case-insensitively, like ``(?i:<expr>)``. Use the
|
|
latter when you need it to apply to only a part of a larger expression.
|
|
|
|
* - ``/<expr>/s``
|
|
- Treats the input as a single line, like ``(?s:<expr>)``. Use the
|
|
latter when you need it to apply to only a part of a larger expression.
|
|
|
|
The speed of regular expression matching does not depend on the complexity or
|
|
size of the patterns.
|
|
|
|
Patterns support two types of matching, exact and embedded.
|
|
In exact matching the ``==`` equality relational operator is used
|
|
with one ``pattern`` operand and one :zeek:type:`string`
|
|
operand (order of operands does not matter) to check whether the full
|
|
string exactly matches the pattern. In exact matching, the ``^``
|
|
beginning-of-line and ``$`` end-of-line anchors are redundant since
|
|
the pattern is implicitly anchored to the beginning and end of the
|
|
line to facilitate an exact match. For example:
|
|
|
|
.. code-block:: zeek
|
|
|
|
/foo|bar/ == "foo"
|
|
|
|
yields true, while:
|
|
|
|
.. code-block:: zeek
|
|
|
|
/foo|bar/ == "foobar"
|
|
|
|
yields false. The ``!=`` operator would yield the negation of ``==``.
|
|
|
|
In embedded matching the ``in`` operator is used with one
|
|
``pattern`` operand (which must be on the left-hand side) and
|
|
one :zeek:type:`string` operand, but tests whether the pattern
|
|
appears anywhere within the given string. For example:
|
|
|
|
.. code-block:: zeek
|
|
|
|
/foo|bar/ in "foobar"
|
|
|
|
yields true, while:
|
|
|
|
.. code-block:: zeek
|
|
|
|
/^oob/ in "foobar"
|
|
|
|
is false since ``"oob"`` does not appear at the start of ``"foobar"``. The
|
|
``!in`` operator would yield the negation of ``in``.
|
|
|
|
Additional examples:
|
|
|
|
- ``/foo+bar/`` matches ``"foobar"`` and ``"fooooobar"``, but not ``"fobar"``.
|
|
- ``/foo*bar/`` matches ``"fobar"``, ``"foobar"``, and ``"fooooobar"``.
|
|
- ``/foo?bar/`` matches ``"fobar"`` and ``"foobar"``, but not ``"fooooobar"``.
|
|
- ``/foo[b-d]ar/`` matches ``"foobar"``, ``"foocar"``, and ``"foodar"``.
|
|
- ``/foo/ | /bar/ in "foobar"`` yields true.
|
|
- ``/foo/ & /bar/ in "foobar"`` yields true, since ``/(foo)(bar)/`` appears in ``"foobar"``.
|
|
- ``/foo|bar/`` matches ``"foo"`` and ``"bar"``.
|
|
- ``/fo(o|b)ar/`` matches ``"fooar"`` and ``"fobar"``, but not ``"foo"`` or ``"bar"``.
|
|
- ``/foo|bar/i`` matches ``"foo"``, ``"Foo"``, ``"BaR"``, etc.
|
|
- ``/foo|(?i:bar)/`` matches ``"foo"`` and ``"BaR"``, but *not* ``"Foo"``.
|
|
- ``/"foo"/i`` matches ``"foo"``, but *not* ``"Foo"``.
|
|
- ``/foo.bar/`` doesn't match ``"foo\nbar"``, while ``/foo.bar/s`` does.
|
|
|
|
The ``i`` and ``s`` modifiers can also be combined in a single pattern
|
|
such as ``/foo/is`` or ``/bar/si``. In this case, both case-insensitivity
|
|
and single-line mode will apply to the pattern.
|
|
|
|
Type Conversions
|
|
^^^^^^^^^^^^^^^^
|
|
|
|
.. list-table::
|
|
:header-rows: 1
|
|
|
|
* - To
|
|
- Description
|
|
- Example
|
|
|
|
* - :zeek:see:`string`
|
|
- :zeek:see:`cat` BIF
|
|
- ``cat(foo)``
|
|
|
|
* - :zeek:see:`string`
|
|
- :zeek:see:`fmt` BIF for additional control over the formatting
|
|
- ``fmt("%s", foo)``
|
|
|
|
|
|
.. zeek:native-type:: port
|
|
|
|
port
|
|
----
|
|
|
|
A type representing transport-level port numbers (besides TCP and
|
|
UDP ports, there is a concept of an ICMP ``port`` where the source
|
|
port is the ICMP message type and the destination port the ICMP
|
|
message code). A ``port`` constant is written as an unsigned integer
|
|
followed by one of ``/tcp``, ``/udp``, ``/icmp``, or ``/unknown``.
|
|
|
|
Ports support the comparison operators (``==``, ``!=``, ``<``, ``<=``,
|
|
``>``, ``>=``). When comparing order across transport-level protocols,
|
|
``unknown`` < ``tcp`` < ``udp`` < ``icmp``, for example ``65535/tcp``
|
|
is smaller than ``0/udp``.
|
|
|
|
Note that you can obtain the transport-level protocol type of a ``port``
|
|
with the :zeek:id:`get_port_transport_proto` built-in function, and
|
|
the numeric value of a ``port`` with the :zeek:id:`port_to_count`
|
|
built-in function.
|
|
|
|
Type Conversions
|
|
^^^^^^^^^^^^^^^^
|
|
|
|
.. list-table::
|
|
:header-rows: 1
|
|
|
|
* - To
|
|
- Description
|
|
- Example
|
|
|
|
* - :zeek:see:`count`
|
|
- :zeek:see:`port_to_count` BIF
|
|
- ``port_to_count(53/udp)``
|
|
|
|
* - :zeek:see:`string`
|
|
- :zeek:see:`cat` BIF
|
|
- ``cat(foo)``
|
|
|
|
* - :zeek:see:`string`
|
|
- :zeek:see:`fmt` BIF for additional control over the formatting
|
|
- ``fmt("%s", foo)``
|
|
|
|
|
|
.. zeek:native-type:: record
|
|
|
|
record
|
|
------
|
|
|
|
A ``record`` is a collection of values. Each value has a field name
|
|
and a type. Values do not need to have the same type and the types
|
|
have no restrictions. Field names must follow the same syntax as
|
|
regular variable names (except that field names are allowed to be the
|
|
same as local or global variables). An example record type
|
|
definition:
|
|
|
|
.. code-block:: zeek
|
|
|
|
type MyRecordType: record {
|
|
c: count;
|
|
s: string &optional;
|
|
};
|
|
|
|
Records can be initialized or assigned as a whole in three different ways.
|
|
When assigning a whole record value, all fields that are not
|
|
:zeek:attr:`&optional` or have a :zeek:attr:`&default` attribute must
|
|
be specified. First, there's a constructor syntax:
|
|
|
|
.. code-block:: zeek
|
|
|
|
local r: MyRecordType = record($c = 7);
|
|
|
|
And the constructor can be explicitly named by type, too, which
|
|
is arguably more readable:
|
|
|
|
.. code-block:: zeek
|
|
|
|
local r = MyRecordType($c = 42);
|
|
|
|
And the third way is like this:
|
|
|
|
.. code-block:: zeek
|
|
|
|
local r: MyRecordType = [$c = 13, $s = "thirteen"];
|
|
|
|
Access to a record field uses the dollar sign (``$``) operator, and
|
|
record fields can be assigned with this:
|
|
|
|
.. code-block:: zeek
|
|
|
|
local r: MyRecordType;
|
|
r$c = 13;
|
|
|
|
To test if a field that is :zeek:attr:`&optional` has been assigned a
|
|
value, use the ``?$`` operator (it returns a :zeek:type:`bool` value of
|
|
``T`` if the field has been assigned a value, or ``F`` if not):
|
|
|
|
.. code-block:: zeek
|
|
|
|
if ( r ?$ s )
|
|
...
|
|
|
|
|
|
.. zeek:native-type:: set
|
|
|
|
set
|
|
---
|
|
|
|
A set is like a :zeek:type:`table`, but it is a collection of indices
|
|
that do not map to any yield value.
|
|
|
|
Declaration and initialization
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
Sets are declared with the syntax::
|
|
|
|
set [ type^+ ]
|
|
|
|
where ``type^+`` is one or more types separated by commas. The index type
|
|
cannot be any of the following types: :zeek:type:`file`, :zeek:type:`opaque`,
|
|
:zeek:type:`any`.
|
|
|
|
Sets can be initialized by listing elements enclosed by curly braces:
|
|
|
|
.. code-block:: zeek
|
|
|
|
global s: set[port] = { 21/tcp, 23/tcp, 80/tcp, 443/tcp };
|
|
global s2: set[port, string] = { [21/tcp, "ftp"], [23/tcp, "telnet"] };
|
|
|
|
A set constructor (equivalent to above example) can also be used to
|
|
create a set:
|
|
|
|
.. code-block:: zeek
|
|
|
|
global s3 = set(21/tcp, 23/tcp, 80/tcp, 443/tcp);
|
|
|
|
Set constructors can also be explicitly named by a type, which is
|
|
useful when a more complex index type could otherwise be
|
|
ambiguous:
|
|
|
|
.. code-block:: zeek
|
|
|
|
type MyRec: record {
|
|
a: count &optional;
|
|
b: count;
|
|
};
|
|
|
|
type MySet: set[MyRec];
|
|
|
|
global s4 = MySet([$b=1], [$b=2]);
|
|
|
|
Insertion and removal
|
|
^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
Elements are added with :zeek:keyword:`add`:
|
|
|
|
.. code-block:: zeek
|
|
|
|
add s[22/tcp];
|
|
|
|
Nothing happens if the element with value ``22/tcp`` was already present in
|
|
the set.
|
|
|
|
Elements are removed with :zeek:keyword:`delete`:
|
|
|
|
.. code-block:: zeek
|
|
|
|
delete s[21/tcp];
|
|
|
|
.. versionadded:: 7.0
|
|
|
|
Removing all set elements can be done with the :zeek:keyword:`delete`, too:
|
|
|
|
.. code-block:: zeek
|
|
|
|
delete s;
|
|
|
|
|
|
Nothing happens if the element with value ``21/tcp`` isn't present in
|
|
the set.
|
|
|
|
Sets behave like tables when it comes to complex member types: indexing happens
|
|
via hashing at access time. See :zeek:type:`table` for details.
|
|
|
|
Lookup and iteration
|
|
^^^^^^^^^^^^^^^^^^^^
|
|
|
|
Set membership is tested with ``in`` or ``!in``:
|
|
|
|
.. code-block:: zeek
|
|
|
|
if ( 21/tcp in s )
|
|
...
|
|
|
|
if ( [21/tcp, "ftp"] !in s2 )
|
|
...
|
|
|
|
See the :zeek:keyword:`for` statement for info on how to iterate over
|
|
the elements in a set.
|
|
|
|
Set operations
|
|
^^^^^^^^^^^^^^
|
|
|
|
You can compute the union, intersection, or difference of two sets
|
|
using the ``|``, ``&``, and ``-`` operators.
|
|
|
|
.. note::
|
|
|
|
Use ``+=`` instead of ``|`` to grow an existing set. That is,
|
|
say ``s += new_s`` instead of ``s = s | new_s``. The latter requires
|
|
copying both input sets and thus quickly deteriorates runtime. See
|
|
:ref:`assignment-operators` for details.
|
|
|
|
You can compare sets for equality (they have exactly the same elements)
|
|
using ``==``. The ``<`` operator returns ``T`` if the lefthand operand
|
|
is a proper subset of the righthand operand. Similarly, ``<=``
|
|
returns ``T`` if the lefthand operator is a subset (not necessarily proper,
|
|
i.e., it may be equal to the righthand operand). The operators ``!=``,
|
|
``>`` and ``>=`` provide the expected complementary operations.
|
|
|
|
Additional operations
|
|
^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
The number of elements in a set can be obtained by placing the set
|
|
identifier between vertical pipe characters:
|
|
|
|
.. code-block:: zeek
|
|
|
|
|s|
|
|
|
|
|
|
The :ref:`table's special lookups <table-special-lookups>` extend to the
|
|
set ``in`` operator: Using ``in`` with ``addr`` and ``set[subnet]``
|
|
or ``string`` and ``set[pattern]`` yields ``T`` if any of the subnets
|
|
or patterns the set holds contain or match the given value.
|
|
|
|
|
|
.. zeek:native-type:: string
|
|
|
|
string
|
|
------
|
|
|
|
A type used to hold bytes which represent text and also can hold
|
|
arbitrary binary data.
|
|
|
|
String constants are created by enclosing text within a pair of double
|
|
quotes (``"``). A string constant cannot span multiple lines in a Zeek script.
|
|
The backslash character (\\) introduces escape sequences. Zeek recognizes
|
|
the following escape sequences: ``\\``, ``\n``, ``\t``, ``\v``, ``\b``,
|
|
``\r``, ``\f``, ``\a``, ``\ooo`` (where each 'o' is an octal digit),
|
|
``\xhh`` (where each 'h' is a hexadecimal digit). If Zeek does not
|
|
recognize an escape sequence, Zeek will ignore the backslash
|
|
(``\\g`` becomes ``g``).
|
|
|
|
Strings support concatenation (``+``), and assignment (``=``, ``+=``).
|
|
Strings also support the comparison operators (``==``, ``!=``, ``<``,
|
|
``<=``, ``>``, ``>=``). The number of characters in a string can be
|
|
found by enclosing the string within pipe characters (e.g., ``|"abc"|``
|
|
is 3). Substring searching can be performed using the ``in`` or ``!in``
|
|
operators (e.g., ``"bar" in "foobar"`` yields true).
|
|
|
|
The subscript operator can extract a substring of a string. To do this,
|
|
specify the starting index to extract (if the starting index is omitted,
|
|
then zero is assumed), followed by a colon and index
|
|
one past the last character to extract (if the last index is omitted,
|
|
then the extracted substring will go to the end of the original string).
|
|
However, if both the colon and last index are omitted, then a string of
|
|
length one is extracted. String indexing is zero-based, but an index
|
|
of -1 refers to the last character in the string, and -2 refers to the
|
|
second-to-last character, etc. Here are a few examples:
|
|
|
|
.. code-block:: zeek
|
|
|
|
local orig = "0123456789";
|
|
local second_char = orig[1]; # "1"
|
|
local last_char = orig[-1]; # "9"
|
|
local first_two_chars = orig[:2]; # "01"
|
|
local last_two_chars = orig[8:]; # "89"
|
|
local no_first_and_last = orig[1:9]; # "12345678"
|
|
local no_first = orig[1:]; # "123456789"
|
|
local no_last = orig[:-1]; # "012345678"
|
|
local copy_orig = orig[:]; # "0123456789"
|
|
|
|
Note that the subscript operator cannot be used to modify a string (i.e.,
|
|
it cannot be on the left side of an assignment operator).
|
|
|
|
Type Conversions
|
|
^^^^^^^^^^^^^^^^
|
|
|
|
.. list-table::
|
|
:header-rows: 1
|
|
|
|
* - To
|
|
- Description
|
|
- Example
|
|
|
|
* - :zeek:see:`addr`
|
|
- :zeek:see:`to_addr` BIF
|
|
- ``to_addr("127.0.0.1")``
|
|
|
|
* - :zeek:see:`addr`
|
|
- :zeek:see:`raw_bytes_to_v4_addr` BIF
|
|
- ``raw_bytes_to_v4_addr("\x7f\x0\x0\x1")``
|
|
|
|
* - :zeek:see:`addr`
|
|
- :zeek:see:`raw_bytes_to_v6_addr` BIF
|
|
- ``raw_bytes_to_v6_addr("\xda\xda\xbe\xef\x00\x00AAAAAAAAAA")``
|
|
|
|
* - :zeek:see:`bool`
|
|
- Relational operator
|
|
- ``foo != ""``
|
|
|
|
* - :zeek:see:`count`
|
|
- :zeek:see:`to_count` BIF
|
|
- ``to_count("42")``
|
|
|
|
* - :zeek:see:`count`
|
|
- :zeek:see:`bytestring_to_count` BIF
|
|
- ``bytestring_to_count("\xde\xad\xbe\xef")``
|
|
|
|
* - :zeek:see:`double`
|
|
- :zeek:see:`to_double` BIF
|
|
- ``to_double("0.001")``
|
|
|
|
* - :zeek:see:`double`
|
|
- :zeek:see:`bytestring_to_double` BIF
|
|
- ``bytestring_to_double("\x43\x26\x4f\xa0\x71\x30\x80\x00")``
|
|
|
|
* - :zeek:see:`int`
|
|
- :zeek:see:`to_int` BIF
|
|
- ``to_int("-42")``
|
|
|
|
* - :zeek:see:`pattern`
|
|
- :zeek:see:`string_to_pattern` BIF
|
|
- ``string_to_pattern("rsh .*", F)``
|
|
|
|
* - :zeek:see:`port`
|
|
- :zeek:see:`to_port` BIF
|
|
- ``to_port("53/udp")``
|
|
|
|
* - :zeek:see:`subnet`
|
|
- :zeek:see:`to_subnet` BIF
|
|
- ``to_subnet("::1/128")``
|
|
|
|
|
|
.. zeek:native-type:: subnet
|
|
|
|
subnet
|
|
------
|
|
|
|
A type representing a block of IP addresses in CIDR notation. A
|
|
``subnet`` constant is written as an :zeek:type:`addr` followed by a
|
|
slash (``/``) and then the network prefix size specified as a decimal
|
|
number. For example, ``192.168.0.0/16`` or ``[fe80::]/64``.
|
|
|
|
Subnets can be compared for equality (``==``, ``!=``). An
|
|
:zeek:type:`addr` can be checked for inclusion in a subnet using
|
|
the ``in`` or ``!in`` operators.
|
|
|
|
Type Conversions
|
|
^^^^^^^^^^^^^^^^
|
|
|
|
.. list-table::
|
|
:header-rows: 1
|
|
|
|
* - To
|
|
- Description
|
|
- Example
|
|
|
|
* - :zeek:see:`addr`
|
|
- :zeek:see:`subnet_to_addr` BIF
|
|
- ``subnet_to_addr([::1]/120)``
|
|
|
|
* - :zeek:see:`double`
|
|
- Absolute value operator
|
|
- ``|1.2.3.0/24|``
|
|
|
|
* - :zeek:see:`string`
|
|
- :zeek:see:`cat` BIF
|
|
- ``cat(foo)``
|
|
|
|
* - :zeek:see:`string`
|
|
- :zeek:see:`fmt` BIF for additional control over the formatting
|
|
- ``fmt("%s", foo)``
|
|
|
|
|
|
.. zeek:native-type:: table
|
|
|
|
table
|
|
-----
|
|
|
|
An associate array that maps from one set of values to another. The
|
|
values being mapped are termed the *index* or *indices* and the
|
|
result of the mapping is called the *yield*. Indexing into tables
|
|
is very efficient, and internally it is just a single hash table
|
|
lookup.
|
|
|
|
Declaration and initialization
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
The table declaration syntax is::
|
|
|
|
table [ type^+ ] of type
|
|
|
|
where ``type^+`` is one or more types, separated by commas. The
|
|
index type cannot be any of the following types: :zeek:type:`file`,
|
|
:zeek:type:`opaque`, :zeek:type:`any`.
|
|
|
|
Here is an example of declaring a table indexed by :zeek:type:`count` values
|
|
and yielding :zeek:type:`string` values:
|
|
|
|
.. code-block:: zeek
|
|
|
|
global a: table[count] of string;
|
|
|
|
The yield type can also be more complex:
|
|
|
|
.. code-block:: zeek
|
|
|
|
global a: table[count] of table[addr, port] of string;
|
|
|
|
which declares a table indexed by :zeek:type:`count` and yielding
|
|
another ``table`` which is indexed by an :zeek:type:`addr`
|
|
and :zeek:type:`port` to yield a :zeek:type:`string`.
|
|
|
|
One way to initialize a table is by enclosing a set of initializers within
|
|
braces, for example:
|
|
|
|
.. code-block:: zeek
|
|
|
|
global t: table[count] of string = {
|
|
[11] = "eleven",
|
|
[5] = "five",
|
|
};
|
|
|
|
A table constructor can also be used to create a table:
|
|
|
|
.. code-block:: zeek
|
|
|
|
global t2 = table(
|
|
[192.168.0.2, 22/tcp] = "ssh",
|
|
[192.168.0.3, 80/tcp] = "http"
|
|
);
|
|
|
|
Table constructors can also be explicitly named by a type, which is
|
|
useful when a more complex index type could otherwise be
|
|
ambiguous:
|
|
|
|
.. code-block:: zeek
|
|
|
|
type MyRec: record {
|
|
a: count &optional;
|
|
b: count;
|
|
};
|
|
|
|
type MyTable: table[MyRec] of string;
|
|
|
|
global t3 = MyTable([[$b=5]] = "b5", [[$b=7]] = "b7");
|
|
|
|
Insertion and removal
|
|
^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
Add or overwrite individual table elements by assignment:
|
|
|
|
.. code-block:: zeek
|
|
|
|
t[13] = "thirteen";
|
|
|
|
Remove individual table elements with :zeek:keyword:`delete`:
|
|
|
|
.. code-block:: zeek
|
|
|
|
delete t[13];
|
|
|
|
Nothing happens if the element with index value ``13`` isn't present in
|
|
the table.
|
|
|
|
.. versionadded:: 7.0
|
|
|
|
Removing all table elements can be done with the :zeek:keyword:`delete`, too:
|
|
|
|
.. code-block:: zeek
|
|
|
|
delete t;
|
|
|
|
.. note::
|
|
|
|
Indexing with complex types (such as records or sets) happens via hashing of
|
|
the provided index value at the time of table access. Subsequent
|
|
modifications to the index value do not affect the table. For example:
|
|
|
|
.. code-block:: zeek
|
|
|
|
local t: table[set[port]] of string = table();
|
|
local s: set[port] = { 80/tcp, 8000/tcp };
|
|
|
|
t[s] = "http";
|
|
|
|
add s[8080/tcp];
|
|
|
|
print t[set(80/tcp, 8000/tcp)]; # prints "http"
|
|
print t[s]; # error: no such index
|
|
|
|
Lookup and iteration
|
|
^^^^^^^^^^^^^^^^^^^^
|
|
|
|
Accessing table elements is provided by enclosing index values within
|
|
square brackets (``[]``), for example:
|
|
|
|
.. code-block:: zeek
|
|
|
|
print t[11];
|
|
|
|
Membership can be tested with ``in`` or ``!in``:
|
|
|
|
.. code-block:: zeek
|
|
|
|
if ( 13 in t )
|
|
...
|
|
if ( [192.168.0.2, 22/tcp] in t2 )
|
|
...
|
|
|
|
See the :zeek:keyword:`for` statement for information on how to iterate over
|
|
the elements in a table.
|
|
|
|
.. _table-special-lookups:
|
|
|
|
Special lookups
|
|
^^^^^^^^^^^^^^^
|
|
|
|
Zeek supports two forms of special table lookups. The first is for tables
|
|
with an index type of :zeek:type:`subnet`. When indexed with an
|
|
:zeek:type:`addr` value, these tables produce the yield associated with
|
|
the closest (narrowest) subnet. For example:
|
|
|
|
.. code-block:: zeek
|
|
|
|
global st: table[subnet] of count;
|
|
st[1.2.3.4/24] = 5;
|
|
st[1.2.3.4/29] = 9;
|
|
print st[1.2.3.4], st[1.2.3.251];
|
|
|
|
will print ``9, 5``. Attempting to look up an address that doesn't match
|
|
any of the subnet indices results in a run-time error.
|
|
|
|
.. versionadded:: 6.2
|
|
|
|
In addition, :zeek:type:`string` lookups for tables that have an index type of
|
|
:zeek:type:`pattern` return a (possibly empty)
|
|
:zeek:type:`vector` containing the values corresponding to each of the
|
|
patterns matching the given string. The order of entries in the resulting
|
|
vector is non-deterministic. For example:
|
|
|
|
.. code-block:: zeek
|
|
|
|
global pt: table[pattern] of count;
|
|
pt[/foo/] = 1;
|
|
pt[/bar/] = 2;
|
|
pt[/(foo|bletch)/] = 3;
|
|
print pt["foo"];
|
|
|
|
will print either ``[1, 3]`` or ``[3, 1]``.
|
|
Indexing with a string that matches only one pattern returns a
|
|
one-element :zeek:type:`vector`, and indexing with a string that no
|
|
pattern matches returns an empty :zeek:type:`vector`.
|
|
|
|
Note that these pattern matches are all *exact*: the pattern must match
|
|
the entire string. If you want the pattern to match if it's *anywhere*
|
|
in the string, you can use the usual regular expression operators such
|
|
as ``/.*foo.*/``.
|
|
|
|
.. note::
|
|
|
|
The :zeek:attr:`&default` attribute is ignored for this type of lookup.
|
|
If none of the patterns matches a given string, the result will be an empty
|
|
:zeek:type:`vector`, regardless of :zeek:attr:`&default`. Neither is the
|
|
:zeek:attr:`&default_insert` attribute used. It's not an error to have
|
|
either of these attributes, however. They'll still be in effect when
|
|
indexing with :zeek:type:`pattern` values.
|
|
|
|
.. note::
|
|
|
|
Internally, Zeek matches a table's patterns in parallel using a lazily
|
|
constructed deterministic finite automaton (DFA). This means that the nature
|
|
of patterns in the table *and* the strings looked up in it can lead to
|
|
varying degrees of runtime memory growth.
|
|
|
|
Users are advised to test scripts using this feature with a wide range of
|
|
input data. Script developers can reset the DFA's state by removal or
|
|
addition of a single pattern. For observability, the
|
|
:zeek:see:`table_pattern_matcher_stats` function returns a
|
|
:zeek:see:`MatcherStats` record with details about a table's DFA state.
|
|
|
|
|
|
Additional operations
|
|
^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
The number of elements in a table can be obtained by placing the table
|
|
identifier between vertical pipe characters:
|
|
|
|
.. code-block:: zeek
|
|
|
|
|t|
|
|
|
|
It's common to extend the behavior of table lookup and membership lifetimes
|
|
via :doc:`attributes <attributes>` but note that it's also a :ref:`confusing
|
|
pitfall <attribute-propagation-pitfalls>` that attributes bind to initial
|
|
*values* instead of *type* or *variable* and do not currently propagate to
|
|
any new *value* subsequently re-assigned to the table *variable*.
|
|
|
|
|
|
.. zeek:native-type:: time
|
|
|
|
time
|
|
----
|
|
|
|
A temporal type representing an absolute time. There is currently
|
|
no way to specify a ``time`` constant, but one can use the
|
|
:zeek:id:`double_to_time`, :zeek:id:`current_time`, or :zeek:id:`network_time`
|
|
built-in functions to assign a value to a ``time``-typed variable.
|
|
|
|
Time values support the comparison operators (``==``, ``!=``, ``<``,
|
|
``<=``, ``>``, ``>=``). A ``time`` value can be subtracted from
|
|
another ``time`` value to produce an :zeek:type:`interval` value. An
|
|
``interval`` value can be added to, or subtracted from, a ``time`` value
|
|
to produce a ``time`` value. The absolute value of a ``time`` value is
|
|
a :zeek:type:`double` with the same numeric value.
|
|
|
|
Type Conversions
|
|
^^^^^^^^^^^^^^^^
|
|
|
|
.. list-table::
|
|
:header-rows: 1
|
|
|
|
* - To
|
|
- Description
|
|
- Example
|
|
|
|
* - :zeek:see:`double`
|
|
- :zeek:see:`time_to_double` BIF
|
|
- ``time_to_double(foo)``
|
|
|
|
* - :zeek:see:`double`
|
|
- Absolute value operator
|
|
- ``|foo|``
|
|
|
|
* - :zeek:see:`interval`
|
|
- Subtraction operator
|
|
- ``end_time - start_time``
|
|
|
|
* - :zeek:see:`string`
|
|
- :zeek:see:`cat` BIF
|
|
- ``cat(foo)``
|
|
|
|
* - :zeek:see:`string`
|
|
- :zeek:see:`fmt` BIF for additional control over the formatting
|
|
- ``fmt("%s", foo)``
|
|
|
|
|
|
.. zeek:native-type:: vector
|
|
|
|
vector
|
|
------
|
|
|
|
A vector is like a :zeek:type:`table`, except its indices are non-negative
|
|
integers, starting from zero.
|
|
|
|
Declaration and initialization
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
A vector is declared as follows:
|
|
|
|
.. code-block:: zeek
|
|
|
|
global v: vector of string;
|
|
|
|
Vectors can be initialized with the vector constructor:
|
|
|
|
.. code-block:: zeek
|
|
|
|
local v = vector("one", "two", "three");
|
|
|
|
Vector constructors can also be explicitly named by a type, which
|
|
is useful for when a more complex yield type could otherwise be
|
|
ambiguous.
|
|
|
|
.. code-block:: zeek
|
|
|
|
type MyRec: record {
|
|
a: count &optional;
|
|
b: count;
|
|
};
|
|
|
|
type MyVec: vector of MyRec;
|
|
|
|
global v2 = MyVec([$b=1], [$b=2], [$b=3]);
|
|
|
|
Insertion
|
|
^^^^^^^^^
|
|
|
|
An element can be added to a vector by assigning the value (a value
|
|
that already exists at that index will be overwritten):
|
|
|
|
.. code-block:: zeek
|
|
|
|
v[3] = "four";
|
|
|
|
A range of elements can be *replaced* by assigning to a vector slice:
|
|
|
|
.. code-block:: zeek
|
|
|
|
# Note that the number of elements in the slice being replaced
|
|
# may differ from the number of elements being inserted. This
|
|
# causes the vector to grow or shrink accordingly.
|
|
v[0:2] = vector("five", "six", "seven");
|
|
|
|
A particularly common operation on a vector is to append an element
|
|
to its end. You can do so using:
|
|
|
|
.. code-block:: zeek
|
|
|
|
v += e;
|
|
|
|
where if *e*'s type is ``X``, *v*'s type is ``vector of X``. Note that
|
|
this expression is equivalent to:
|
|
|
|
.. code-block:: zeek
|
|
|
|
v[|v|] = e;
|
|
|
|
In addition, if *e*'s type is ``vector of X`` and so is *v*'s type, then
|
|
|
|
.. code-block:: zeek
|
|
|
|
v += e;
|
|
|
|
instead appends each element of *e* to *v*. (In this case the expression
|
|
is *not* equivalent to ``v[|v|] = e``, which will generate an error because
|
|
*e*'s type is not compatible with ``X``.)
|
|
|
|
Lookup and iteration
|
|
^^^^^^^^^^^^^^^^^^^^
|
|
|
|
Access individual vector elements by enclosing index values within
|
|
square brackets (``[]``), for example:
|
|
|
|
.. code-block:: zeek
|
|
|
|
print v[2];
|
|
|
|
Access a slice of vector elements by enclosing a range of indices,
|
|
delimited by a colon, within square brackets (``[x:y]``). For example,
|
|
this will print a vector containing the first and second elements:
|
|
|
|
.. code-block:: zeek
|
|
|
|
print v[0:2];
|
|
|
|
The slicing notation is the same as what is permitted by the
|
|
:zeek:see:`string` substring extraction operations.
|
|
|
|
The ``in`` operator can be used to check if a value has been assigned at a
|
|
specified index value in the vector. For example, if a vector has size 4,
|
|
then the expression ``3 in v`` would yield true and ``4 in v`` would yield
|
|
false.
|
|
|
|
See the :zeek:keyword:`for` statement for info on how to iterate over
|
|
the elements in a vector.
|
|
|
|
.. versionadded:: 7.0
|
|
|
|
The :zeek:keyword:`delete` statement can be used to delete all elements
|
|
from a vector.
|
|
|
|
Vectorized operations
|
|
^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
Vectors of integral types (:zeek:type:`int` or :zeek:type:`count`) support the pre-increment
|
|
(``++``) and pre-decrement operators (``--``), which will increment or
|
|
decrement each element in the vector.
|
|
|
|
Vectors of arithmetic types (:zeek:type:`int` or :zeek:type:`count`, or :zeek:type:`double`) can be
|
|
operands of the arithmetic operators (``+``, ``-``, ``*``, ``/``, ``%``),
|
|
but both operands must have the same number of elements (and the modulus
|
|
operator ``%`` cannot be used if either operand is a ``vector of double``).
|
|
The resulting vector contains the result of the operation applied to each
|
|
of the elements in the operand vectors.
|
|
|
|
Vectors of :zeek:type:`bool` can be operands of the logical "and" (``&&``) and logical
|
|
"or" (``||``) operators (both operands must have the same number of elements).
|
|
The resulting ``vector of bool`` is the logical "and" (or logical "or") of
|
|
each element of the operand vectors.
|
|
|
|
Vectors of :zeek:type:`count` can also be operands for the bitwise and/or/xor
|
|
operators, ``&``, ``|`` and ``^``.
|
|
|
|
Vectors of :zeek:type:`string` can be concatenated element-wise through
|
|
the ``+`` operator, yielding a new ``vector of string`` containing the
|
|
resulting values. Both operand vectors must be of the same length. A
|
|
vector of type :zeek:type:`string` can also be paired with a scalar operand
|
|
using any operator that supports string/scalar operations (i.e.,
|
|
concatenation and comparisons). The resulting vector will contain the
|
|
result of the operator applied to each of the elements.
|
|
|
|
.. note::
|
|
|
|
As a quirk of the language, for a string vector ``v`` there is a
|
|
difference between ``v = v + "foo"`` and ``v += "foo"``: the former
|
|
extends each element, while the latter appends a new element to the
|
|
vector.)
|
|
|
|
Additional operations
|
|
^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
The size of a vector (this is one greater than the highest index value, and
|
|
is normally equal to the number of elements in the vector) can be obtained
|
|
by placing the vector identifier between vertical pipe characters:
|
|
|
|
.. code-block:: zeek
|
|
|
|
|v|
|
|
|
|
|
|
.. zeek:native-type:: void
|
|
|
|
void
|
|
----
|
|
|
|
An internal Zeek type (i.e., ``void`` is not a reserved keyword in the Zeek
|
|
scripting language) representing the absence of a return type for a
|
|
function.
|