如何打印多次出现在TCLvariables中的单词(URL名称)?

以下是我的TCL脚本:

set line { Jul 24 21:06:40 2014: %AUTH-6-INFO: login[1765]: user 'admin' on 'pts/1' logged Jul 24 21:05:15 2014: %DATAPLANE-5-: Unrecognized HTTP URL www.58.net. Flow: 0x2 Jul 24 21:04:39 2014: %DATAPLANE-5-: Unrecognized HTTP URL static.58.com. Flow: Jul 24 21:04:38 2014: %DATAPLANE-5-: Unrecognized HTTP URL www.google-analytics. com. Flow: 0x2265394048. Jul 24 21:04:36 2014: %DATAPLANE-5-: Unrecognized HTTP URL track.58.co.in. Flow: 0 } if {[regexp -all {Unrecognized HTTP URL ([a-z0-9.]*) Flow} $line junk one]} { puts $one } 

使用上面的TCL脚本,我想grep的“$行”variables的URL名称。 现在,我们只能grep只显示在结尾(track.58.co.in。)的URL名称。 如何使用TCL正则expression式来grep所有的URL名称。

此外,我想将这些grepped URL名称导出到Microsoft Excel文件。如何做到这一点? 请帮助我的想法。

谢谢,

巴卢

(我原来的回答是有点乱,有点改变了,这个更好一些,请注意,我现在的答案和glenn jackman的答案非常相似,但是还有一些细微的差别。答案被接受了,我把它保留在文本的末尾。)

代替

 if {[regexp -all {Unrecognized HTTP URL ([a-z0-9.]*) Flow} $line junk one]} { puts $one } 

使用

 set urls {} foreach {junk url} [regexp -all -inline {Unrecognized HTTP URL ([a-z0-9.]*) Flow} $line] { lappend urls [string trim $url .] } 

或(Tcl 8.6+)

 set urls [lmap {junk url} [regexp -all -inline {Unrecognized HTTP URL ([a-z0-9.]*) Flow} $line] {string trim $url .}] 

使用-all和variable名称调用regexp将最后一组匹配存储在这些variables中,并返回true或false,指示是否匹配。 用-inline会返回一个列表,它是所有匹配集合的连接(如果这个列表是空的,则不匹配)。 通过在这种情况下使用foreachlmap遍历返回的列表并挑选出您想要的项目,您可以收集一个url列表。

日志在每个你可能不想要的url后面加上一个点,然后string trim $url . 修复(它也将删除前导点,如果他们出现)。 使用正则expression式{Unrecognized HTTP URL ([a-z0-9.]*)\. Flow} {Unrecognized HTTP URL ([a-z0-9.]*)\. Flow}{Unrecognized HTTP URL (.*?)\. Flow} {Unrecognized HTTP URL (.*?)\. Flow}是另一种解决方法,通过从捕获中排除该点。

请注意,您使用的正则expression式不匹配所有有效的url,而且它会匹配一些无效的url(因为您正在提取实际login的url,所以这里不是一个很大的问题)。 具体而言,由于“com”之前的换行符,它错过了第三个url。 如果这是一个问题,故意超过url可能是有意义的:

 regexp -all -inline {Unrecognized HTTP URL (.*?) Flow} $line 

它使用非贪婪匹配来拾取“URL”和“Flow”之间的任何内容 (包括embedded的空格)。 在接下来的步骤中,您可以通过一个filter来传递url列表,这个filter会丢弃或标记任何对您来说看起来不合法的url。

将URL导出到Excel最简单的方法应该是将它们写入文本文件:

 package require fileutil ::fileutil::writeFile urllist.txt [join $urls \n]\n 

或者(再次假定Tcl 8.6)

 try { open urllist.txt w } on ok f { chan puts $f [join $urls \n] } finally { catch {chan close $f} } 

然后在Excel中打开文件; 每个URL将位于自己行的第一列。

文档: catch , chan , if , join , lappend , lmap , open , package , regexp , set , string , try

老答案

您可以使用此命令获取所有url:

 lmap item [regexp -all -inline {URL\s+\S+} $line] { string trimright [lindex $item 1] . } 

如果你使用-all和variables(在你的情况下, junkone ),你只能得到最后一场比赛。 相反,使用-all-inline ,它们会给你一个匹配列表。 您只需要匹配序列"URL" ,一个或多个空格字符( \s+ ),然后再匹配一个非空格字符序列( \S+ )。 这给你的名单

 {{URL www.58.net} {URL static.58.com} {URL www.google-analytics} {URL track.58.co.in}} 

如果$line部分与正则expression式不匹配,则列表将为空。

如果你想打印所有的URL,你可以写:

 set urls [lmap item [regexp -all -inline {URL\s+\S+} $line] { string trimright [lindex $item 1] . }] foreach url $urls { puts $url } 

如果你有Tcl 8.6,你可以使用lmap命令将这个列表映射到另一个列表,这个列表包含第一个列表中每个元素的第二个元素。

如果你有一个老版本的Tcl,应该这样做:

 set urls [list] foreach item [regexp -all -inline {URL\s+\S+} $line] { lappend urls [string trimright [lindex $item 1] .] } foreach url $urls { puts $url } 

现在,您可以在正则expression式的\S+中使用一个捕获来获取一个列表,其中每个其他元素(元素#1,#3等)都是URL,但是这实际上使得它更难一点得到url列表(glenn jackman在他的回答中采取了这个路线)。

请注意,第三个url已损坏,因为其中有空白区域。 粘贴这个例子的时候会发生这种情况吗,或者真正的数据中是否会出现这样的空白字符?

(如何导出到Excel的说明移到新答案。)

文档: catch , chan , foreach , lappend , lindex , lmap , open , puts , regexp , set , string , try

(注:评论中提到的“Hoodiecrow”是我的,我之前用过那个。)

 % regexp -inline -all {HTTP URL (\S+)\.} $line {HTTP URL www.58.net.} www.58.net {HTTP URL static.58.com.} static.58.com {HTTP URL www.google-analytics.} www.google-analytics {HTTP URL track.58.co.in.} track.58.co.in % foreach {match submatch} [regexp -inline -all {HTTP URL (\S+)\.} $line] { lappend urls $submatch } % set urls www.58.net static.58.com www.google-analytics track.58.co.in