hexHunt is a procedure that will collectively hunt line by line for the start of and end of an specific tag, using hexadecimal character pattern searching.
In this example we are checking the conditions that % is the first character, and that _ is next in sequence, that _ is second to last, and % is the last. In which if so, concludes we have a correctly formatted tag. Collect and store and do whatever with like execute an word to tag swap mechanism.
This works well in template systems where you need to replace a placeholder tag with actual data from a source. You would populate a document with an placeholder like: %_title_% which would be replaced with the site title "hexHunt Example".
Example:
Using the string of: This is an example of <b>%_hex_hunt_%</b>
hex string: 5468697320697320616e206578616d706c65206f66203c623e255f6865785f68756e745f253c2f623e
Returns the tag %_hex_hunt_%
The tags can be defined within the procedure checkTag where % and _ are represented by their hex values
proc checkTag { args } { set tag [lindex $args 0] ;# What we are looking for set hexBlock [lindex $args 1] ;# our hexBlock [a2 b3 d4] # switch $tag # This checks to see if the tag provided exists within the block given # Cases: # Tag # Description # Result # % | Activate a switch on our hexChar to see if it contains "25" | returns value: 1 # _ | Activate a switch on our hexChar to see if it contains "5f" | returns value: 1 switch $tag { "%" { switch $hexBlock { 25 { return 1 } } } "_" { switch $hexBlock { 5f { return 1 } } } } ;# end switch } ;# end proc proc hexHunt { args } { set range "" set tagKeys "" set za 0 ;# This is used as our list index # x = index of cursor 1 at first index # y = index of cursor 2 at second index # z = string length count set lines [binary encode hex "This is an example of <b>%_hex_hunt_%</b>"] foreach line $lines { set list "" set string_length [string length $line] for { lassign {0 1 0} x y z } {$z < $string_length} {incr z} { ## lappend list [string range $line $x $y] ;# append our two characters of our hexString incr x 2 ; incr y 2 ;# Increase both of our cursors by two switch [string range $line $x $y] { "" { break } } ;# if we than reach the end of our string characters break # we do this because our string length is not our character length ## } ;# end for foreach item $list { # puts "is my item a % at index $za | [binary decode hex $item] | $item" set hexBlock $item ;# Get our two characters from our hex string # switch checkTag "%" # This checks to see if the tag provided exists within the block given # Cases: # 1 | We have a valid tag, increase our block to the next element, and check if the next element matches _ # default | We have a valid tag, decrease our block to the previous element and check if the previous block matches _ switch [checkTag "%" $hexBlock] { 1 { # puts "yes! at index $za" # puts "Is my next element an _ at index [expr $za+1] ?" set hexBlock [lindex $list [expr $za +1]] ;# increase our hex character by plus one to check our next element # switch checkTag "_" # This checks to see if the tag provided exists within the block given # Cases: # 1 | We have a valid tag sequence, return our hexBlock to the previous value, # set the index to where we located the tag # default | The character was not a _ so we now check the previous characters switch [checkTag "_" $hexBlock] { 1 { # puts "it is, so a valid tag match!" # puts "set our starting range!" # decrease our za index to return to us to previous proper value set hexBlock [lindex $list [expr $za -1]] set locatedAt $za # } default { # puts "No it's not, what about the previous?" set hexBlock [lindex $list [expr $za -1]] ;# set our hexBlock to the previous index # switch checkTag "_" # This checks to see if the tag provided exists within the block given # Cases: # 1 | We have a valid tag sequence, return our hexBlock to the previous value # default | the previous block was not a _ switch [checkTag "_" $hexBlock] { 1 { # puts "It is! so a valid match!" set hexBlock [lindex $list [expr $za +1]] ### # switch [llength $locatedAt] # This checks to see if we have a starting range # Cases: # 0 | we have no starting range | break, as this will end up with malformed results # 1 | We have a valid tag sequence, # appended our tag we've collected switch [llength $locatedAt] { 0 { puts "We have no starting range" ; break } 1 { # puts "append range!" ; ## append the range of where we located our tag and where we are currently at # lappend range $locatedAt $za ;# shows the discovered ranges of our tags lappend tagKeys [binary decode hex [lrange $list $locatedAt $za]] set locatedAt "" ;# reset our locatedAt for next loop iteration ## } } } default { # puts "No it wasn't" set hexChar [lindex $list [expr $za -1]] } } } } } } ;# end switch [checkTag "%" $hexBlock] incr za } ;# end foreach item set za 0 } ;# end foreach line puts "Discovered tag: $tagKeys" } ;# end proc
Output
% hexHunt Discovered tag: %_hex_hunt_%