2013-10-04 22 views
0

新的網站,所以忍受着我。我正在開發一個Tcl/Expect腳本,並嘗試匹配以下路由器輸出中的第4行的一部分(顯示了兩個可能的輸出)。它通常都會有一個IP地址,但可能有像第二樣品中的字符串:Tcl /期待正則表達式 - 想使懶惰(而不是貪婪)

Routing entry for 10.1.1.0/30 
    Known via "static", distance 1, metric 0 
    Routing Descriptor Blocks: 
    * 10.3.3.1 
     Route metric is 0, traffic share count is 1 

另一種可能的輸出:

Routing entry for 10.1.2.0/24 
    Known via "static", distance 220, metric 0 (connected) 
    Advertised by bgp 1234 
    Routing Descriptor Blocks: 
    * directly connected, via Null0 
     Route metric is 0, traffic share count is 1 

我希望聲明,使用正則表達式,如下:

expect -re "Routing Descriptor Blocks:\r\n \\\* (.*)\r\n" { 
     set next_hop $expect_out(1,string) 
     puts "\n\n*Next-hop address is: $next_hop*\n" 
} 

(3個反斜槓都讓他們通過Tcl的分析得到的,並且*的交給正則表達式的解釋,以匹配一個星號。)

我的問題是 - 毫不奇怪 - 這是做一個「貪婪的」匹配,我不需要貪婪。請參閱調試輸出,其中明確:

expect: does "show ip route 10.1.1.0\r\nRouting entry for 10.1.1.0/30\r\n Known via "static", distance 1, metric 0\r\n Routing Descriptor Blocks:\r\n * 10.3.3.1\r\n  Route metric is 0, traffic share count is 1\r\n\r\nRouter>" (spawn_id 4) match regular expression "Routing Descriptor Blocks:\r\n \* (.*)\r\n"? yes 
expect: set expect_out(0,string) "Routing Descriptor Blocks:\r\n * 10.3.3.1\r\n Route metric is 0, traffic share count is 1\r\n\r\n" 
expect: set expect_out(1,string) "10.3.3.1\r\n  Route metric is 0, traffic share count is 1\r\n" 

我想要在FIRST \ r \ n停止匹配。

因此,對於非貪婪的比賽,我還以爲我需要添加一個「?」如下:

expect -re "Routing Descriptor Blocks:\r\n \\\* (.*?)\r\n" { 
     set next_hop $expect_out(1,string) 
     puts "\n\n*Next-hop address is: $next_hop*\n" 
} 

問題是,這似乎並不奏效。我從調試輸出如下:

bad regular expression: nested *?+ 
    while executing 
"expect -re "Routing Descriptor Blocks:\r\n \\\* (.*?)\r\n" { 
     set next_hop $expect_out(1,string) 
     puts "\n\n*Next-hop address is: $next_hop*\n" 
}" 
    (file "./test_telnet_to_router.exp" line 23) 

我在這個一直盯着太久了,所以以爲我會要求一些幫助。我需要做什麼來獲得我需要的懶惰比賽的任何想法?請注意,我堅持在此HP-UX服務器上僅使用基本正則表達式...擴展正則表達式不可用。

謝謝, 詹姆斯

+0

這是什麼Tcl版本? (在交互式期望或tclsh會話中,'info patchlevel') –

+0

expect1.1> info patchlevel 7.4 感謝您花時間看這個! – James

回答

1

哇,這是老了。 Almost 20 years old。任何可能的升級可能性?做一個懶惰的比賽

一種方法是尋找不屬於特殊字符字符的貪婪序列。這可能工作

-re "Routing Descriptor Blocks:\r\n \\\* (\[^\n\]+)\n" 

另一種選擇是做貪婪的匹配,然後拆分新行上捕獲的部分。

在這兩種情況下,您都必須手動刪除尾部回車符。

+0

這樣做了,謝謝。現在我被我無法用'string trimright $ next_hop'或者甚至'string trimright $ next_hop「\ r」'刪除尾部回車符的事實難倒了。我查看了與Tcl 7.5相同的文檔,並且字符串trimright命令似乎已經出現了一段時間......任何想法?當我將變量打印出來時,尾隨回車符號仍然存在。 – James

+0

hmm。如果你知道*那裏有一個CR,你可以使用(深呼吸)'[字符串範圍$ next_hop 0 [expr {[字符串長度$ next_hop] - 2}]]' –

+0

虛假警報!我在別處做錯了事。字符串trimright實際上工作,但我沒有保存修剪版本打印之前...我的Perl過去,我猜。 我現在全部設置。非常感謝你的幫助。 – James

1

的Tcl 7.4是從過去一個真正的爆炸,它使用的是不支持非貪婪的RE在RE所有發動機(很舊的)版本。 (對RE引擎的改變發生在Tcl 8.0中,現在仍然已經有十多年的歷史了,而且還不支持很長時間...)

解決這個問題的最簡單的機制是更多在你的正則表達式中特定於你想要匹配的內容。特別是,如果您不希望在捕獲的部分內匹配換行符,請不要使用(.*),而要使用([^\n]*)。既然你把RE雙引號,你真正需要使用這樣的:

expect -re "Routing Descriptor Blocks:\r\n \\* (\[^\n\]*)\r\n" { 
    set next_hop $expect_out(1,string) 
    puts "\n\n*Next-hop address is: $next_hop*\n" 
} 

這一切都是假設你不想Route metric…線。最簡單的方法來捕獲,如果你想要它添加另一個(無新行捕獲)的一塊RE的結束,所以它最終作爲$expect_out(2,string)

expect -re "Routing Descriptor Blocks:\r\n \\* (\[^\n\]*)\r\n *(\[^\n\]*)\r\n" { 
    set next_hop $expect_out(1,string) 
    puts "\n\n*Next-hop address is: $next_hop*\n" 
    puts "Extra info: $expect_out(2,string)" 
} 

一般來說,使用Expect時儘可能使用REs儘可能精確。它有助於。但是請記住,您可以同時指望幾個不同的RE ...

+0

你說得對,這是舊東西......這些傢伙把「如果有效的話不要碰它」進入下一個階段。不幸的是,對此無能爲力。 你的[第一]建議工作得很好,謝謝(我不需要路線指標...線)。 現在我正在努力去除尾隨\ r,正如您可能從我的評論中看到的第一個答案。 – James

+0

@James我對預期或舊版Tcl不太瞭解,但是如果使用正則表達式'\ [^ \ n \ r \] *'而不是'\ [^ \ n \] *'? – Jerry

+0

謝謝,@Jerry ...我曾嘗試過但它不匹配。但我現在都已經設定了(請參閱我對上述答案的評論)。感謝您的支持! – James