Intermediate iRules: Handling Lists

We've talked about variables in the Getting Started with iRules series, but we're going to cover specifically the list object type of variable. Most of the TCL commands for use in manipulating lists are available in iRules:

  • list - Create a list
  • split - Split a string into a proper Tcl list
  • join - Create a string by joining together list elements
  • concat - Join lists together
  • llength - Count the number of elements in a list
  • lindex - Retrieve an element from a list
  • lrange - Return one or more adjacent elements from a list
  • linsert - Insert elements into a list
  • lreplace - Replace elements in a list with new elements
  • lsort - Sort the elements of a list
  • lsearch - See if a list contains a particular element

The remaining documented list handling commands, lrepeat, lreverse, & dict, are not available within iRules. We’ll cover the commands from above that get the most traffic here on DevCentral.

split

 

split string ?splitChars?

 

Returns a list created by splitting string at each character that is in the splitChars argument. Each element of the result list will consist of the characters from string that lie between instances of the characters in splitChars. Empty list elements will be generated if string contains adjacent characters in splitChars, or if the first or last character of string is in splitChars. If splitChars is an empty string then each character of string becomes a separate element of the result list. SplitChars defaults to the standard white-space characters. In this example, the split command is used to separate the hours/minutes/seconds returned from the formatted clock command into separate list elements:

 

% set caTime [clock format [clock seconds] -format {%H:%M:%S}]
10:38:30
% set l [split $caTime :]
10 38 30

 

join

 

join string ?splitChars?

 

The list argument must be a valid Tcl list. This command returns the string formed by joining all of the elements of list together with joinString separating each adjacent pair of elements. The joinString argument defaults to a space character. In this example, the user is building the IP address using the join command and the “.” as the splitChar.

 

foreach num $IPtmp {
  lappend IP [expr ($num + 0x100) % 0x100]
}
set ::attr_value1 [join $IP .]

 

Using a TCL shell, the output follows:

 

% set IPtmp { 0x8c 0xaf 0x55 0x44 }
0x8c 0xaf 0x55 0x44
% foreach num $IPtmp {
lappend IP [expr ($num + 0x100) % 0x100]
}
% puts $IP
140 175 85 68
% set IP [join $IP .]
140.175.85.68

 

concat

 

concat ?arg arg … ?

 

This command joins each of its arguments together with spaces after trimming leading and trailing white-space from each of them. If all the arguments are lists, this has the same effect as concatenating them into a single list. It permits any number of arguments; if no args are supplied, the result is an empty string. Here’s an excellent example of the concat command, which joins the contents of a cookie with the values from LB::server and virtual name:

 

HTTP::cookie insert path / name ltmcookie value [concat [virtual name] [LB::server]]

 

using the TCL shell, need variables in place of the calls to [virtual name] and [LB::server]:

 

% set virtual_name myVip
myVip
% set lb_server "myPool 10.10.10.10 443"
myPool 10.10.10.10 443
% set ltmcookie_value [concat $virtual_name $lb_server]
myVip myPool 10.10.10.10 443

 

lindex

 

lindex list ?index … ?

 

This command accepts a parameter, list, which it treats as a Tcl list. It also accepts zero or more indices into the list. The indices may be presented either consecutively on the command line, or grouped in a Tcl list and presented as a single argument. This example, from the same iRule as the concat example above, shows the extraction of the list elements into usable variables:

 

set vipid [lindex [HTTP::cookie ltmcookie] 0]
set poolid [lindex [HTTP::cookie ltmcookie] 1]
set serverid [lindex [HTTP::cookie ltmcookie] 2]
set portid [lindex [HTTP::cookie ltmcookie] 3]

 

Using the cookie variable we set in the above concat example, we can now extract the list items:

 

% set vipid [lindex $ltmcookie_value 0]
myVip
% set poolid [lindex $ltmcookie_value 1]
myPool
% set serverid [lindex $ltmcookie_value 2]
10.10.10.10
% set portid [lindex $ltmcookie_value 3]
443

 

Better to avoid the variables, but a good illustration none-the-less. Often you’ll see the split and lindex commands used together:

 

set trimID [lindex [split [HTTP::cookie "JSESSIONID"] "!" ] 0]
Stepping through that, you can see first the split occur, then the indexing:
% set jsessionID_cookie "zytPJpxV0TnpssqZZRLBgsVMLhGS6M2ZNMZ622yCNvpv0gkpTwzn!956498630!-34852364"
zytPJpxV0TnpssqZZRLBgsVMLhGS6M2ZNMZ622yCNvpv0gkpTwzn!956498630!-34852364
% set l [split $jsessionID_cookie !]
zytPJpxV0TnpssqZZRLBgsVMLhGS6M2ZNMZ622yCNvpv0gkpTwzn 956498630 -34852364
% set jsessID [lindex $l 0]
zytPJpxV0TnpssqZZRLBgsVMLhGS6M2ZNMZ622yCNvpv0gkpTwzn

 

There is a shortcut command in iRules for the split and lindex command pairing called getfield. Note that whereas lindex begins at 0, getfield begins at 1. The example below shows a direct comparison:

# lindex/split
set trimID [lindex [split [HTTP::cookie "JSESSIONID"] "!"] 0]

# getfield
set trimID [getfield [HTTP::cookie "JSESSIONID"] "!" 1]

Note that using iRules-specific commands might help readability, but doing so does require a jump from the Tcl virtual machine back over to TMM to process. In this case it's incredibility negligible, but if you are squeezing out every CPU cycle it's something to be aware of.

Updated Oct 02, 2023
Version 3.0
No CommentsBe the first to comment