NAME
Config::INI::RefVars - INI file reader that supports make-style variable references and multiple assignment operators.
VERSION
Version 0.17
SYNOPSIS
use Config::INI::RefVars;
my $ini_reader = Config::INI::RefVars->new();
$ini_reader->parse_ini(src => $my_ini_file);
my $variables = $ini_reader->variables;
while (my ($section, $section_vars) = each(%$variables)) {
# ...
}
If the INI file contains:
section = $(=)
[sec A]
foo=Variable $(==) in section $(section)
bar:=$(foo)
foo.=!
[sec B]
baz = from $(=): ref foo from sec A: $([sec A]foo)
then $ini_reader->variables
returns:
{
'__TOCOPY__' => {
'section' => '__TOCOPY__'
},
'sec A' => {
'bar' => 'Variable foo in section sec A',
'foo' => 'Variable foo in section sec A!',
'section' => 'sec A'
},
'sec B' => {
'baz' => 'from sec B: ref foo from sec A: Variable foo in section sec A!',
'section' => 'sec B'
}
}
DESCRIPTION
INTRODUCTION
This module provides an INI file reader that allows INI variables and environment variables to be referenced within the INI file. It also supports some additional assignment operators.
Minimum version of perl required to use this module: v5.10.1
.
OVERVIEW
A line in an INI file should not start with an =
or the sequence ;!
. These are reserved for future extensions. Otherwise the parser throws a "Directives are not yet supported" exception. Apart from these special cases, the following rules apply:
Spaces at the beginning and end of each line are ignored.
If the first non-white character of a line is a
;
or a#
, then the line is a comment line.Comments can also be specified to the right of a section declaration (in this case, the comment must not contain closing square brackets).
In a section header, spaces to the right of the opening square bracket and to the left of the closing square bracket are ignored, i.e. a section name always begins and ends with a non-white character. But: As a special case, the name of a section heading can be an empty character string.
Section name must be unique.
The order of the sections is retained: The
sections
method returns an array of sections in the order in which they appear in the INI file.A variable name cannot be empty.
The sequence
$(...)
is used to reference INI variables or environment variables.Spaces around the assignment operator are ignored. Note that there are several assignment operators, not just
=
.If you want to define a variable whose name ends with an punctuation character other than an underscore, there must be at least one space between the variable name and the assignment operator.
The source to be parsed (argument
src
of the methodparse_ini
) does not have to be a file, but can also be a string or an array.There is no escape character.
You will find further details in the following sections.
SECTIONS
A section begins with a section header:
[section]
A line contains a section heading if the first non-blank character is a [
and the last non-blank character is a ]
. The character string in between is the name of the section, whereby spaces to the right of [
and to the left of ]
are ignored.
[ The name of the section ]
This sets the section name to The name of the section
.
As a special case, []
or [ ]
are permitted, which results in a section name that is just an empty string.
Section names must be unique.
An INI file does not have to start with a section header, it can also start with variable definitions. In this case, the variables are added to the tocopy section (default name: __TOCOPY__
). You can explicitly specify the tocopy section heading, but then this must be the first active line in your INI file.
VARIABLES AND ASSIGNMENT OPERATORS
There are several assignment operators, the basic one is the =
, the others are formed by a =
preceded by one or more punctuation characters. Thus, if you want to define a variable whose name ends with an punctuation character, there must be at least one space between the variable name and the assignment operator.
Note: Since the use of the underscore in identifiers is so common, it is not treated as a punctuation character here.
=
-
The standard assignment operator. Note: A second assignment to the same variable simply overwrites the first.
?=
-
Works like the corresponding operator of GNU Make: the assignment is only executed if the variable is not yet defined.
??=
-
This works similar to
?=
: the assignment is only executed if the variable is not yet defined or if its current, non-expanded value is an empty string.This allows you to set a default value for an environment variable:
env_var:=$(=ENV:ENV_VAR) env_var??=the default
If the environment variable
ENV_VAR
is not defined or is empty, thenenv_var
has the valuethe default
. This would not work with?=
. Please note that you must also use:=
! :=
-
Works like the corresponding operator of GNU Make: all references to other variables are expanded when the variable is defined. See section "REFERENCING VARIABLES"
.=
-
The right-hand side is appended to the value of the variable. If the variable is not yet defined, this does the same as a simple
=
.Example:
var=abc var.=123
Now
var
has the valueabc123
. +=
-
Works like the corresponding operator of GNU Make: the right-hand side is appended to the value of the variable, separated by a space. If the right-hand side is empty, a space is appended. If the variable is not yet defined, this has the same effect as a simple
=
.Example:
var=abc var+=123
Now
var
has the valueabc 123
. .>=
-
The right-hand side is placed in front of the value of the variable. If the variable is not yet defined, this has the same effect as a simple
=
.Example:
var=abc var.>=123
Now
var
has the value123abc
. +>=
-
The right-hand side is placed in front the value of the variable, separated by a space. If the right-hand side is empty, a space is placed in front of the variable value. If the variable is not yet defined, this has the same effect as a simple
=
.Example:
var=abc var+>=123
Now
var
has the value123 abc
.
REFERENCING VARIABLES
Basic Referencing
The referencing of variables is similar but not identical to that in make, you use $(VARIABLE)
. Example:
a=hello
b=world
c=$(a) $(b)
Variable c
has the value hello world
. As with make, lazy evaluation is used, i.e. you would achieve exactly the same result with this:
c=$(a) $(b)
a=hello
b=world
But the following would result in c
containing only one space:
c:=$(a) $(b)
a=hello
b=world
Unlike in make, the round brackets cannot be omitted for variables with only one letter!
You can nest variable references:
foo=the foo value
var 1=fo
var 2=o
bar=$($(var 1)$(var 2))
Now the variable bar
has the value the foo value
.
A reference to a non-existent variable is always expanded to an empty character string.
If you need a literal $(...)
sequence, e.g. $(FOO)
, as part of a variable value, you can write:
var = $$()(FOO)
This results in the variable var
having the value $(FOO)
. It works because $()
always expands to an empty string (see section "PREDEFINED VARIABLES").
Recursive references are not possible, an attempt to do so leads to a fatal error. However, you can do this with the :=
assignment:
a=omethin
a:=s$(a)g
a
has the value something
. However, due to the way :=
works, this is not really a recursive reference.
Referencing Variables of other Sections
By default, you can reference a variable in another section by writing the name of the section in square brackets, followed by the name of the variable:
[sec A]
foo=Referencing a variable from section: $([sec B]bar)
[sec B]
bar=Referenced!
You can switch to a different notation by specifying the constructor argument separator
.
A more complex example:
[A]
a var = 1234567
[B]
b var = a var
nested = $([$([C]c var)]$(b var))
[C]
c var = A
Variable nested
in section B
has the value 1234567
.
PREDEFINED VARIABLES
Variables related to Section and Variable Names
=
-
$(=)
expands to the name of the current section. ==
-
$(==)
expands to the name of the variable that is currently being defined. Think of this as a pseudo-variable, something like $([SECTION]==) always results in an empty string.
Example:
[A]
foo=variable $(==) of section $(=)
ref=Reference to foo of section B: $([B]foo)
[B]
foo=variable $(==) of section $(=)
bar=$(foo)
The hash returned by the variables
method is then:
{
'A' => {
'foo' => 'variable foo of section A',
'ref' => 'Reference to foo of section B: variable foo of section B'
},
'B' => {
'foo' => 'variable foo of section B'
'bar' => 'variable foo of section B',
}
}
Variables related to the Source
=srcname
-
Name of the INI source. If the source is a file, this corresponds to the value that you have passed to
parse_ini
via thesrc
argument, otherwise it is set to "INI data". The value can be overwritten with the argumentsrc_name
. =INIdir
,=INIfile
-
Directory (absolute path) and file name of the INI file. These variables are only present if the source is a file, otherwise they are not defined.
Variables related to the OS
=:
-
The directory separator,
\
on Windows,/
on Linux. Note: This is not always sufficient to create a path, e.g. on VMS. =::
-
Path separator, which is used in the environment variable
PATH
, for example.
Space Variables
$()
always expands to an empty string, $( )
, $( )
with any number of spaces within the parens expand to exactly these spaces. So there are several ways to define variables with heading or trailing spaces:
foo = abc $()
bar = $( )abc
The value of foo
has three spaces at the end, the value of bar
has three spaces at the beginning. A special use case for $()
is the avoidance of unwanted variable expansion:
var=hello!
x=$(var)
y=$$()(var)
With these settings, x
has the value Hello!
, but y
has the value $(var)
.
Other Variables
=TO_CP_SEC
-
Name of the tocopy section, see "THE TOCOPY SECTION".
=VERSION
-
Version of the
Config::INI::RefVars
module.
Custom predefined Variables
Currently, custom predefined variables are not supported. But you can do something very similar, see argument tocopy_vars
(of new
and parse_ini
), see also "THE TOCOPY SECTION". With this argument you can also define variables whose names contain a =
, which is obviously impossible in an INI file.
Predefined Variables in resulting Hash
By default, all variables whose names contain a =
are removed from the resulting hash. This means that the variables discussed above are not normally included in the result. This behavior can be changed with the parse_ini
argument cleanup
. The variable ==
can of course not be included in the result.
ACCESSING ENVIRONMENT AND CONFIG VARIABLES
You can access environment variables with this $(=ENV:...)
or this $(=env:...)
notation. Example:
path = $(=ENV:PATH)
path
now contains the content of your environment variable PATH
.
The results of $(=ENV:...)
and $(=env:...)
are almost always the same. The difference is that the parser always leaves the value of $(=ENV:...)
unchanged, but tries to expand the value of $(=env:...)
. For example, let's assume you have an environment variable FOO
with the value $(var)
and you write this in your INI file:
var=hello!
x=$(=ENV:FOO)
y=$(=env:FOO)
This results in x
having the value $(var)
, while y
has the value hello!
.
You can access configuration variables of Perl's Config module with this $(=CONFIG:...)
notation. Example:
the archlib=$(=CONFIG:archlib)
This gives the variable the archlib
the value of $Config{archlib}
.
Note: In contrast to $(=ENV:...)
, there is no lower-case counterpart to $(=CONFIG:...)
, as this would not make sense.
THE TOCOPY SECTION
Default Behavior
If specified, the method parse_ini
copies the variables of the tocopy section (default name: __TOCOPY__
) to any other section when the INI file is read (default, this behavior can be changed by the constructor argument global_mode
). For example this
[__TOCOPY__]
some var=some value
section info=$(=)
[A]
[B]
is exactly the same as this:
[__TOCOPY__]
some var=some
section info=$(=)
[A]
some var=some
section info=$(=)
[B]
some var=some
section info=$(=)
Of course, you can change or overwrite a variable copied from the tocopy
section locally within a section at any time without any side effects. In this case, you can access the original value as follows:
$([__TOCOPY__]some var)
or - more generally - like this:
$([$(=TO_CP_SEC)]some var)
You can exclude variables with the argument not_tocopy
from copying (methods new
and parse_ini
), but there is currently no notation to do this in the INI file.
The tocopy section is optional. If it is specified, it must be the first section. By default, its name is __TOCOPY__
, this can be changed with the argument tocopy_section
(methods new
and parse_ini
). You can omit the [__TOCOPY__]
header and simply start your INI file with variable definitions. These then simply become the tocopy section. So this:
[__TOCOPY__]
a=this
b=that
[sec]
x=y
is exactly the same as this:
a=this
b=that
[sec]
x=y
You can also add tocopy variables via the argument tocopy_vars
(methods new
and parse_ini
), these are treated as if they were at the very beginning of the tocopy
section.
Global Mode
If you specify the constructor argument global_mode
with a true value, the variables of the tocopy section are not copied, but behave like global variables. Variables that you specify with the argument not_tocopy
are not treated as global.
Consequently, there is almost no difference in the referencing of variables if you use the global mode. The advantage of this mode is that you do not clutter your sections with unwanted variables.
Example:
[__TOCOPY__]
a=this
b=that
[sec]
x=y
This would lead to this result by default:
{
__TOCOPY__ => {a => 'this', b => 'that'},
sec => {a => 'this', b => 'that', x => 'y'}
}
But in global mode the result is:
{
__TOCOPY__ => {a => 'this', b => 'that'},
sec => {x => 'y'}
}
For a local copy of a global variable, use assignment operator :=
.
NOTE: In some special cases, variables have different values in standard mode than in global mode.
section=$(=)
x=GLOBAL
x_val=$(x)
[local-sec]
var_1 := $(section)
var_2 = $(section)
x=LOCAL
x_1 := $(x_val)
x_2 = $(x_val)
By default, you will get:
{
'__TOCOPY__' => {
'section' => '__TOCOPY__',
'x' => 'GLOBAL',
'x_val' => 'GLOBAL'
},
'local-sec' => {
'section' => 'local-sec',
'var_1' => 'local-sec',
'var_2' => 'local-sec',
'x' => 'LOCAL',
'x_1' => 'LOCAL',
'x_2' => 'LOCAL',
'x_val' => 'LOCAL'
}
}
But in global mode, the result is:
{
'__TOCOPY__' => {
'section' => '__TOCOPY__',
'x' => 'GLOBAL',
'x_val' => 'GLOBAL'
},
'local-sec' => {
'var_1' => 'local-sec',
'var_2' => '__TOCOPY__',
'x' => 'LOCAL',
'x_1' => 'LOCAL',
'x_2' => 'GLOBAL'
}
}
Note the different values for var_2
and x_2
. When the assignment x_1 := $(x_val)
is reached, the right-hand side is evaluated immediately, so that $(x_val)
becomes $(x)
, which in turn leads to LOCAL
, since the definition of x
in [local-sec]
shadows the global x
.
In contrast, the value of x_2
is evaluated after the file has been completely read. This value is $(x_val)
and the variable x_val
was in turn previously evaluated in the global section and has the value GLOBAL
, which then becomes the value of x_2
.
In standard mode, x_val=$(x)
is copied to [local-sec]
and x_2
is given the value LOCAL
due to the local definition of x
.
A corresponding explanation applies to the different values of var_2
.
COMMENTS
As said, if the first non-white character of a line is a ;
or a #
, then the line is a comment line.
# This is a comment
; This is also a comment
;! a comment, but: avoid ";!" at the very beginning of a line!
var = value ; this is not a comment but part of the value.
Avoid ;!
at the very beginning of a line, otherwise you will get an error. The reason for this is that this sequence is reserved for future extensions. However, you can use it if you precede it with spaces.
You cannot append a comment to the right of a variable definition, as your comment would otherwise become part of the variable value. But you can append a comment to the right of a header declaration:
[section] ; My fancy section
Attention: if you do this, the comment must not contain a ]
character!
PITFALLS
In most cases, the keys in the hash returned by variables
are the same as the keys in the hash returned by the sections_h
method and the entries in the array returned by the sections
method. In special cases, however, there may be a difference with regard to the tocopy section. Example:
[A]
a=1
[B]
b=2
If you parse this INI source like this:
my $obj = Config::INI::RefVars->new();
$obj->parse_ini(src => $src, tocopy_vars => {'foo' => 'xyz'});
then the variables
method returns this:
'A' => {
'a' => '1',
'foo' => 'xyz'
},
'B' => {
'b' => '2',
'foo' => 'xyz'
},
'__TOCOPY__' => {
'foo' => 'xyz'
}
but sections_h
returns
{ 'A' => '0',
'B' => '1' }
and sections
returns
['A', 'B']
No __TOCOPY__
. The reason for this is that the return values of sections_h
and sections
refer to what is contained in the source, and in this case __TOCOPY__
is not contained in the source, but comes from a method argument.
METHODS
new
The constructor takes the following optional named arguments:
cmnt_vl
-
Optional, a Boolean value. If this value is set to true, comments are permitted in variable lines. The comment character is a semicolon preceded by one or more spaces.
Example:
[section] var 1=val 1 ; comment var 2=val 2 ; ; ; comment var 3=val 3; no comment var 4=val 4 $(); no comment
After parsing, the
variables
method returns:section => {'var 1' => 'val 1', 'var 2' => 'val 2', 'var 3' => 'val 3; no comment', 'var 4' => 'val 4 ; no comment', }
Default is false (
undef
). global_mode
-
Optional, a boolean. Cheanges handling of the tocopy section, see section "Global Mode". See also the accessor method of the same name.
not_tocopy
-
Optional, a reference to a hash or an array of strings. The hash keys or array entries specify a list of variables that should not be copied from the tocopy section to the other sections. It does not matter whether these variables actually occur in the tocopy section or not.
Default is
undef
. separator
-
Optional, a string. If specified, an alternative notation can be used for referencing variables in another section. Example:
my $obj = Config::INI::RefVars->new(separator => '::');
Then you can write:
[A] y=27 [B] a var=$(A::y)
This gives the variable
a var
the value27
.The following characters are permitted for
separator
:#!%&',./:~\
See also the accessor method of the same name.
tocopy_section
-
Optional, a string. Specifies a different name for the tocopy section. Default is
__TOCOPY__
. See accessortocopy_section
. tocopy_vars
-
Optional, a hash reference. If specified, its keys become variables of the tocopy section, the hash values become the corresponding variable values. This allows you to specify variables that you cannot specify in the INI file, e.g. variables with a
=
in the name.Keys with
=
or;
as the first character are not permitted.Default is
undef
. varname_chk_re
-
Optional, a compiled regex. If specified, each variable name defined in the INI source must match this regex.
Example:
my $obj = Config::INI::RefVars->new(varname_chk_re => qr/^[A-Z]/); my $src = <<'EOT'; [the section] A=the value xYZ=123 Z1=z2 Y= EOT $obj->parse_ini(src => $src);
This will result in an exception with the message
'xYZ': var name does not match varname_chk_re
.
current_tocopy_section
Returns the name of the section tocopy that was used the last time parse_ini
was called. Please note that the section does not have to be present in the data.
See also method tocopy_section
.
global_mode
Returns a boolean value indicating whether the global mode is activated or not. See constructor argument of the same name, see also section "Global Mode".
parse_ini
Parses an INI source. The method takes the following optional named arguments:
src
-
Mandatory, a string or an array reference. This specifies the source to parse. If it is a character string that does not contain a newline character, it is treated as the name of an INI file. Otherwise, its content is parsed directly.
cleanup
-
Optional, a boolean. If this value is set to false, variables with a
=
in their name are not removed from the resulting hash that is returned by thevariables
method. But in global mode, most of this variables will not be contained, see section "Global Mode".Default is 1 (true)
tocopy_section
-
Optional, a string. Specifies a different name for the tocopy section for this run only. The previous value is restored before the method returns. Default is the string returned by accessor
tocopy_section
.See constructor argument of the same name.
tocopy_vars
-
Optional, overwrites the corresponding setting saved in the object for this run only. The previous setting is restored before the method returns.
See constructor argument of the same name.
not_tocopy
-
Optional, overwrites the corresponding setting saved in the object for this run only. The previous setting is restored before the method returns.
See constructor argument of the same name.
src_name
-
Optional, overwrites the corresponding setting saved in the object for this run only. The previous setting is restored before the method returns.
See constructor argument of the same name, see also the accessor os the same name.
sections
Returns a reference to an array of section names from the INI source, in the order in which they appear there.
sections_h
Returns a reference to a hash whose keys are the section names from the INI source, the values are the corresponding indices in the array returned by sections
.
separator
Returns the value that was passed to the constructor via the argument of the same name, or undef
.
src_name
Returns the name of the INI source (file name that you have passed to parse_ini
via the argument src
, or the one that you have passed via the argument src_name
, or "INI data
", see section "Variables in relation to the source".
tocopy_section
Returns the name of the tocopy section that will be used as the default for the next call to parse_ini
.
See also method current_tocopy_section
.
variables
Returns a reference to a hash of hashes. The keys are the section names, each value is the corresponding hash of varibales (key: variable name, value: variable value). By default, variables with a =
in their name are not included; this can be changed with the cleanup
argument.
EXAMPLES
You can parse INI files as described here $(section\name) syntax for INI file variables as follows:
my $obj = Config::INI::RefVars->new(separator => "\\",
cmnt_vl => 1,
tocopy_section => 'Settings',
global_mode => 1);
my $src = <<'EOT';
[Settings]
BaseDir="d:\dhcpsrv" ; dhcpsrv.exe resides here
IPBIND_1=192.168.17.2
IPPOOL_1=$(Settings\IPBIND_1)-50
AssociateBindsToPools=1
Trace=1
TraceFile="$(BaseDir)\dhcptrc.txt" ; trace file
[DNS-Settings]
EnableDNS=1
[General]
SUBNETMASK=255.255.255.0
DNS_1=$(IPBIND_1)
[TFTP-Settings]
EnableTFTP=1
Root="$(BaseDir)\wwwroot" ; use wwwroot for http and tftp
[HTTP-Settings]
EnableHTTP=1
Root="$(BaseDir)\wwwroot" ; use wwwroot for http and tftp
EOT
$obj->parse_ini(src => $src);
SEE ALSO
$(section\name) syntax for INI file variables
This one allows also referencing variables: Config::IOD::Reader.
Other modules handling INI files:
Config::INI, Config::INI::Tiny, Config::IniFiles, and many more.
AUTHOR
Abdul al Hazred, <451 at gmx.eu>
BUGS
Please report any bugs or feature requests to bug-config-ini-accvars at rt.cpan.org
, or through the web interface at https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Config-INI-RefVars. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.
SUPPORT
You can find documentation for this module with the perldoc command.
perldoc Config::INI::RefVars
You can also look for information at:
RT: CPAN's request tracker (report bugs here)
https://rt.cpan.org/NoAuth/Bugs.html?Dist=Config-INI-RefVars
Search CPAN
GitHub Repository
LICENSE AND COPYRIGHT
This software is copyright (c) 2023 by Abdul al Hazred.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.