问题
I have two types of interfaces "Ethernet9/12/1 and Ethernet8/34". I wanted to parse both type of interfaces using single regular expression.
I was trying to achieve this in the below manner:
set int "Ethernet9/12/1"
regexp -nocase "(.*t)((\\d+)\/(\\d+)/\(\\d+))" $int - int_type int_num mod_num port broken_port
puts $int_type
puts $int_num
puts $mod_num
puts $port
puts $broken_port
This code works for Ethernet9/12/1. But, the same regexp does not work for Ethernet8/34. I need help to achieve this in the single regexp using TCL.
Kindly help.
回答1:
You need to make the last part optional with a non-capturing group:
regexp -nocase "(.*t)((\\d+)\/(\\d+)(?:/(\\d+))?)" $int - int_type int_num mod_num port broken_port
^^^ ^^
See IDEONE Tcl demo
Output:
Ethernet
8/34
8
34
A non-capturing group is only meant to group subpatterns and does not interfere with the capturing groups you already defined to be used later.
回答2:
Just make the second part optional with ?:
(.*t)((\d+)\/(\d+)(?:\/(\d+))?)
Tested on regex101
NOTE: I escaped your / characters with a \ but that might flavor specific.
回答3:
The code becomes a lot more manageable if one doesn't concentrate all processing within the regular expressions.
set int Ethernet9/12/1
regexp -nocase {(.+t)(.*)} $int -> int_type int_num
lassign [split $int_num /] mod_num port broken_port
puts [list $int_type $int_num $mod_num $port $broken_port]
# -> Ethernet 9/12/1 9 12 1
set int Ethernet8/34
regexp -nocase {(.+t)(.*)} $int -> int_type int_num
lassign [split $int_num /] mod_num port broken_port
puts [list $int_type $int_num $mod_num $port $broken_port]
# -> Ethernet 8/34 8 34 {}
Documentation: lassign, list, puts, regexp, set, split, Syntax of Tcl regular expressions
来源:https://stackoverflow.com/questions/38255800/tcl-regular-expression