tcl字符串操作替换
CL:字符串命令
有⼀个关于TCL的哲学探讨:TCL语法中的⼀切是否都是字符串?(以及这是不是⼀件好事),但是⽆论你的论点如何,你都⽆法否认字符串在TCL语法中扮演着⾮常重要的⾓⾊,iRules也是⼀样。TCL提供了许多的字符串命令,其中的⼀些会在本⽂中提及。
string map
string range
string trim
string trimleft
string trimright
我们将会看到这⼏条命令的⼏个具体案例,主要是因为我仍然觉得其它⼈在TCL⽂档中使⽤的例⼦实在是太少了。
string map ?-nocase? mapping string
在字符串中,替换⼦串是其于映射中的Key-Value对。映射是指⼀个key value key value ... 的列表,字符串中每⼀个Key的实例都会被它所对应的Value所取代。如果指定了-nocase模式,那么匹配就会执⾏,⽽不考虑⼤⼩写的差异。Key和Value都可能是⼀个多重字符。替换是按特定的顺序进⾏的,所以在列表中第⼀个出现的Key就会被第⼀个选中,依此类推。下⾯的⼀个例⼦是由论坛⽹友Hoolio提供的,有两种映射模式,⽤Https取代Http,并把服务器端⼝号去掉。
when HTTP_RESPONSE {
# Check if a response is a redirect 查看响应是不是⼀个重定向。
if {[HTTP::is_redirect]}{
log local0. "Original Location: [HTTP::header value Location]"
# Assume the server will use it's own TCP port in redirects and remove it.  Also replace with .
#假设服务器会在重定向时使⽤它⾃⼰的TCP端⼝并把它去掉。同时⽤ 替换
HTTP::header replace Location [string map -nocase ]list ":[LB::server port]" ""[ ]HTTP::header value Location[]
log local0. "Updated location (string map): [string map -nocase ]list ":[LB::server port]" ""[ ]HTTP::header value Location[]"
}
}
字符串只进⾏⼀次迭代,所以先前替换的Key不会影响到之后的Key匹配。例如:
% string map {abc 1 ab 2 a 3 1 0} 1abcaababcabababc
01321221
什么?这是TCL⽂档⾥的⼀个不那么直观的例⼦。但事实上,我⾮常喜欢它。我们来详细的分析⼀下。这个例⼦⾥有四个key/value对abc, if found, will be replaced by a 1        abc,如果有的话,会被1替代
ab, if found, will be replaced by a 2          ab,如果有的话,会被2替代
a, if found, will be replaced by a 3          a,如果有的话,会被3替代
1, if found, will be replaced by a 0          1,如果有的话,会被0替代
String Map Multiple Key/Value Example
Mapping Original String Resulting String
1st (abc->1)1abcaababcabababc11aab1abab1
2nd (ab->2)11aab1abab111a21221
3rd (a->3)11a2122111321221
4th (1->0)1132122101321221
注意看第四组映射,返回的字符串是01321221,⽽不是00320220。为什么呢?这是因为字符串只进⾏⼀次迭代,所以先前替换的Key不会影响到之后的Key匹配。
string range string first last
返回字符串⾥某⼀范围内的连续字符,以索引⾥的第⼀个字符起始,以索引⾥的最后⼀个字符结束。索引值为零指的就是字符串⾥的第⼀个字符,起始和结束是由索引⽅式来指定的。如果起始值⼩于零,那就当它当做零来处理,如果结束值⼤于等于字符串长度,就把它当做结尾。如果起始值⼤于结束值,则会返回⼀个空的字符串。Colin成功的提出了⼀个通过字符串范围来删除Host⾥的已知端⼝的例⼦。请注意他⾮常漂亮的使⽤了0作为起始,以end-5作为结束。当然,这个问题可以通过getfield命令更简便,更轻松的解决,但那是另⼀回事。
when HTTP_REQUEST {
if { [HTTP::host] ends_with "8010" } {
set http_host [string range ]HTTP::host[ 0 end-5]
HTTP::redirect "$http_host[HTTP::uri]"
}
}
在这个例⼦⾥,⽹友unRuleY提供了⼀个去掉URI中最前⾯⼏个字符的解决⽅案:
when HTTP_REQUEST {
set uri [HTTP::uri]
if { $uri starts_with "/axess2" } {
HTTP::uri [string range $uri 7 end]
}
}
string trim string ?chars?
字符串剪切 字符串?符号?
返回⼀个除了删除出现在字符串⾸尾的字符,其余都和原来⼀样的字符串。如果没有指定符号,那么空⽩(空格,tab,换⾏和回车)会被删除。在我刚开始写iRules的时候,我并不理解这些,以及trimleft和trimright。trimleft和trimright分别⽤来删除串⾸和串尾的字符,但trim可以同时删除⾸尾的字符。这⾥有些Shell下的例⼦来解释这⼀⾏为:
% set a ". this is a string ."
. this is a string .
% string trim $a .
this is a string                                          # notice the . was trimmed, but not the whitespace注意.被剪切掉了,但是空格没有
% string trim [string trim $a .] " "
this is a string                                          # now the whitespace has been trimmed (both leading and trailing)现在⾸和尾的空格都被剪切了
% string trim [string trim $a .]
this is a string                                              # same as before, the " " isn't necessary, removed by default when ?chars? isn't specified                和上⾯的例⼦⼀样,只是没有必要使⽤“ ”,不指定符号时候⼀样可以默认的进⾏删除。
% set b [string trim ]string trim $a .[]<EOS>
this is a string<EOS>                                    # Just added <EOS> to show the whitespace has in fact been trimmed from the trailing end of the string          添加了⼀个<EOS>来显⽰字符串末尾的空格的确是被去掉了。
%
Trimleft和trimright的⼯作⽅式是⼀样的。他们在匹配时并不剪切字符串⾸尾的字符,⽽是将匹配上的字符删掉。这⾥有⼀个Colin的例⼦,他⽤trimleft命令删除了路径中的第⼀个字符。需要注意的是,我们在上⾯那个使⽤字符串范围的例⼦⾥也解决了同样的问题。你将会遇到的问题中的⼤部分都是有多种解决⽅法的,在这个例⼦中,路径是指定的,这就使得Rules要⽐字符串范围的命令更简单,尤其是你所有的路径都以/xyz/开始的时候。
重定向过多是什么意思when HTTP_REQUEST {
if {[HTTP::host] contains "soa"} {
if {[HTTP::uri] starts_with "/prd/"} {
HTTP::uri [string trimleft ]HTTP::uri[ /prd]
pool POOL_SOA_PRD
}
if {[HTTP::uri] starts_with "/ppd/"} {
HTTP::uri [string trimleft ]HTTP::uri[ /ppd]
pool POOL_SOA_PPD
# THIS IS ONLY HERE SO THAT THEY CAN KEEP TESTING      pool POOL_SOA_PRD
}
}
}

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。