Reformatting for readability:
if { [string first "PRIV" $vs] == "0"} {
regsub {_VIP$} $vs "" parser
} else {
regsub {_PERMVIP$} $vs "" parser
}
set counter [llength [split $parser "_"]]
set appporttype [getfield $parser "_" $counter]
regsub $appporttype$ $parser "" parser1
regsub {_$} $parser1 "" parser
The first if conditional checks to see if the variable $vs (which is set somewhere above the code block you provided) starts with the string "PRIV" (in an iRule, it is generally better to say if { $vs starts_with "PRIV" }, by the way). To be pedantic, string first $needle $haystack returns the offset (starting at 0) of the first instance of $needle in $haystack (or -1 if it is not found). So, this checks if PRIV is at offset 0 (meaning at the beginning) of the string referenced by $vs.
If the value referenced by the variable $vs starts with "PRIV", then it strips the string literal _VIP from the end of the value in $vs, assigning the resulting value to a variable named "parser". Pedantically, regsub exp str subst var evaluates the regular expression "exp" against the variable "str" and replaces a match with "substr", assigning the value to "var". In this code, "exp" is {_VIP$}. Squirly braces ({...}) are non-interpolating quote operators (so they are just quotes around a string) and the actual expression is _VIP$. In Tcl regexp, the dollar-sign ($) at the end means "match the preceding string (_VIP, in this case) if-and-only-if it is at the very end". (For what it's worth, regular expressions should generally be avoided in iRules. This same function can be done a number of different ways, but a reasonably easy one is: set parser [string range $vs 0 [expr { [string last "_VIP" $vs] - 1 }]]. That might look nasty, but it takes half the execution time of the regsub method).
If the value referenced by the variable $vs does not start with the literal PRIV, then the else clause code strips the literal _PERMVIP from the end of the value referenced by $vs, and sets the result to the variable "parser".
Said very briefly, then: if the string referenced by $vs starts with PRIV, strip _VIP from the end of that string and assign the result to $parser; otherwise, strip _PERMVIP from the end of that string and assign the result to $parser.
The next line treats the value of the variable $parser as a series of labels delimited by underscores (_). It sets a variable called "counter" to the number of such labels. The line after that gets the last label and assigns it to a variable called "appporttype" (again, for what it's worth, since the split was already done on the previous line, these two lines could have been reduced to: set appporttype [lindex [split $parser _] end]).
The next line two lines remove the last label from the string apppporttype and assigns the value back to the variable called "parser".
Okay, putting it all together: if, at the start of this block, $vs is "PRIV_ABC_DEF_VIP", then, at the end, $parser will be "PRIV_ABC". It stripeed _VIP from the end (because it starts with PRIV_), then removes the label before _VIP (_DEF, in this example).
Were I writing this logic, I might do something like this instead:
if { $vs starts_with PRIV } {
remove _VIP from the end of $vs
set parser [string range $vs 0 [expr { [string last "_VIP" $vs] - 1 }]]
} else {
remove _PERMVIP from the end of $vs
set parser [string range $vs 0 [expr { [string last "_PERMVIP" $vs] - 1 }]]
}
remove the last label that starts with underscore (_) from $parser
set parser [string range $parser 0 [expr { [string last _ $parser] - 1 }]]
(An alternative to the last line -- and keeping with the list creation in the original -- could be: set parser [join [lrange [split $parser _] 0 end-1] _], but that is quite a bit slower).