Variable Expansion
Keywords: misc

Subsections

- General Functionality
- Bacula Variables
- Full Syntax
- Semantics
- Examples

#
Variable Expansion

Please note that as of version 1.37, the Variable Expansion is deprecated and replaced by Python scripting (not yet documented).

Variable expansion is somewhat similar to Unix shell variable expansion. Currently (version 1.31), it is used only in format labels, but in the future, it will most likely be used in more places.

# General Functionality

This is basically a string expansion capability that permits referencing variables, indexing arrays, conditional replacement of variables, case conversion, substring selection, regular expression matching and replacement, character class replacement, padding strings, repeated expansion in a user controlled loop, support of arithmetic expressions in the loop start, step and end conditions, and recursive expansion.

When using variable expansion characters in a Volume Label Format record, the format should always be enclosed in double quotes (").

For example, ${HOME} will be replaced by your home directory as defined in the environment. If you have defined the variable xxx to be Test, then the reference ${xxx:p/7/Y/r} will right pad the contents of xxx to a length of seven characters filling with the character Y giving YYYTest.

# Bacula Variables

Within Bacula, there are three main classes of variables with some minor variations within the classes. The classes are:

Counters
  Counters are defined by the Counter resources in the Director's conf file. The counter can either be a temporary counter that lasts for the duration of Bacula's execution, or it can be a variable that is stored in the catalog, and thus retains its value from one Bacula execution to another. Counter variables may be incremented by postfixing a plus sign (+ after the variable name).

Internal Variables
  Internal variables are read-only, and may be related to the current job (i.e. Job name), or maybe special variables such as the date and time. The following variables are available:

  Year
    - the full year
  Month
    - the current month 1-12
  Day
    - the day of the month 1-31
  Hour
    - the hour 0-24
  Minute
    - the current minute 0-59
  Second
    - the current second 0-59
  WeekDay
    - the current day of the week 0-6 with 0 being Sunday
  Job
    - the job name
  general
    - the Director's name
  Level
    - the Job Level
  Type
    - the Job type
  JobId
    - the JobId
  JobName
    - the unique job name composed of Job and date
  Storage
    - the Storage daemon's name
  Client
    - the Client's name
  NumVols
    - the current number of Volumes in the Pool
  Pool
    - the Pool name
  Catalog
    - the Catalog name
  MediaType
    - the Media Type

Environment Variables
  Environment variables are read-only, and must be defined in the environment prior to executing Bacula. Environment variables may be either scalar or an array, where the elements of the array are referenced by subscripting the variable name (e.g. ${Months[3]}). Environment variable arrays are defined by separating the elements with a vertical bar (|), thus set Months="Jan|Feb|Mar|Apr|..." defines an environment variable named Month that will be treated as an array, and the reference ${Months[3]} will yield Mar. The elements of the array can have differing lengths.

# Full Syntax

Since the syntax is quite extensive, below, you will find the pseudo BNF. The special characters have the following meaning:

     ::=     definition
     ( )     grouping if the parens are not quoted
     |       separates alternatives
     '/'     literal / (or any other character)
     CAPS    a character or character sequence
     *       preceding item can be repeated zero or more times
     ?       preceding item can appear zero or one time
     +       preceding item must appear one or more times

And the pseudo BNF describing the syntax is:

     input       ::= ( TEXT
                     | variable
                     | INDEX_OPEN input INDEX_CLOSE (loop_limits)?
                     )*
     variable    ::= DELIM_INIT (name|expression)
     name        ::= (NAME_CHARS)+
     expression  ::= DELIM_OPEN
                     (name|variable)+
                     (INDEX_OPEN num_exp INDEX_CLOSE)?
                     (':' command)*
                     DELIM_CLOSE
     command     ::= '-' (TEXT_EXP|variable)+
                   | '+' (TEXT_EXP|variable)+
                   | 'o' NUMBER ('-'|',') (NUMBER)?
                   | '#'
                   | '*' (TEXT_EXP|variable)+
                   | 's' '/' (TEXT_PATTERN)+
                         '/' (variable|TEXT_SUBST)*
                         '/' ('m'|'g'|'i'|'t')*
                   | 'y' '/' (variable|TEXT_SUBST)+
                         '/' (variable|TEXT_SUBST)*
                         '/'
                   | 'p' '/' NUMBER
                         '/' (variable|TEXT_SUBST)*
                         '/' ('r'|'l'|'c')
                   | '%' (name|variable)+
                         ('(' (TEXT_ARGS)? ')')?
                   | 'l'
                   | 'u'
     num_exp     ::= operand
                   | operand ('+'|'-'|'*'|'/'|'%') num_exp
     operand     ::= ('+'|'-')? NUMBER
                   | INDEX_MARK
                   | '(' num_exp ')'
                   | variable
     loop_limits ::= DELIM_OPEN
                     (num_exp)? ',' (num_exp)? (',' (num_exp)?)?
                     DELIM_CLOSE
     NUMBER      ::= ('0'|...|'9')+
     TEXT_PATTERN::= (^('/'))+
     TEXT_SUBST  ::= (^(DELIM_INIT|'/'))+
     TEXT_ARGS   ::= (^(DELIM_INIT|')'))+
     TEXT_EXP    ::= (^(DELIM_INIT|DELIM_CLOSE|':'|'+'))+
     TEXT        ::= (^(DELIM_INIT|INDEX_OPEN|INDEX_CLOSE))+
     DELIM_INIT  ::= '$'
     DELIM_OPEN  ::= '{'
     DELIM_CLOSE ::= '}'
     INDEX_OPEN  ::= '['
     INDEX_CLOSE ::= ']'
     INDEX_MARK  ::= '#'
     NAME_CHARS  ::= 'a'|...|'z'|'A'|...|'Z'|'0'|...|'9'

# Semantics

The items listed in command above, which always follow a colon (:) have the following meanings:

     -    perform substitution if variable is empty
     +    perform substitution if variable is not empty
     o    cut out substring of the variable value
     #    length of the variable value
     *    substitute empty string if the variable value is not empty,
          otherwise substitute the trailing parameter
     s    regular expression search and replace. The trailing
          options are: m = multiline, i = case insensitive,
                       g = global,    t = plain text (no regexp)
     y    transpose characters from class A to class B
     p    pad variable to l = left, r = right or c = center,
          with second value.
     %    special function call (none implemented)
     l    lower case the variable value
     u    upper case the variable value

The loop_limits are start, step, and end values.

A counter variable name followed immediately by a plus (+) will cause the counter to be incremented by one.

# Examples

To create an ISO date:

      DLT-${Year}-${Month:p/2/0/r}-${Day:p/2/0/r}

on 20 June 2003 would give DLT-2003-06-20

If you set the environment variable mon to

       January|February|March|April|May|...
       File-${mon[${Month}]}/${Day}/${Year}

on the first of March would give File-March/1/2003