2

I have a string xxxxxxx-s12345ab7_0_0_xx2.log and need to have an output like AB700_xx2 in TCL.

ab will be the delimiter and need to extract from ab to . (including ab) and also have to remove only the first two underscores.

Tried string trim, string trimleft and string trimright, but not much use. Is there anything like string split in TCL?

Donal Fellows
  • 133,037
  • 18
  • 149
  • 215
user2902205
  • 69
  • 2
  • 8
  • 1
    Can you explain the structure of the string? Is the `ab` delimiter always the same? Are the *7*, *0*, *0* always single digits? Is the *x* an *any character* placeholder? – Marco Pallante Oct 21 '13 at 08:32
  • 1
    `string trim*` isn't the right tool for this job, and `string split` is just called `split`… – Donal Fellows Oct 21 '13 at 08:53

3 Answers3

4

The first stage is to extract the basic relevant substring; the easiest way to do that is actually with a regular expression:

set inputString "xxxxxxx-s12345ab7_0_0_xx2.log"

if {![regexp {ab[^.]+} $inputString extracted]} {
    error "didn't match!"
}
puts "got $extracted"
# ===> got ab7_0_0_xx2

Then, we want to get rid of those nasty underscores with string map:

set final [string map {"_" ""} $extracted]
puts "got $final"
# ===> ab700xx2

Hmm, not quite what we wanted! We wanted to keep the last underscore and to up-case the first part.

set pieces [split $extracted "_"]
set final [string toupper [join [lrange $pieces 0 2] ""]]_[join [lrange $pieces 3 end] "_"]
puts "got $final"
# ===> got AB700_xx2

(The split command divides a string up into “records” by an optional record specifier — which defaults to any whitespace character — that we can then manipulate easily with list operations. The join command does the reverse, but here I'm using an empty record specifier on one half which makes everything be concatenated. I think you can guess what the string toupper and lrange commands do…)

Donal Fellows
  • 133,037
  • 18
  • 149
  • 215
  • I would do `regsub -all {_(\d)} $extracted {\1} final` to remove the "inner" underscores, give or take unspoken requirements. – glenn jackman Oct 21 '13 at 15:25
0
set a "xxxxxxx-s12345ab7_0_0_xx2.log"
set a [split $a ""]
set trig 0
set extract ""
for {set i 0} {$i < [llength $a]} {incr i} {
    if {"ab" eq "[lindex $a $i][lindex $a [expr $i+1]]"} {
        set trig 1
    }
    if {$trig == 1} {
        append extract [lindex $a $i]
    }
}

set extract "[string toupper [join [lrange [split [lindex [split $extract .] 0] _] 0 end-1] ""]]_[lindex [split [lindex [split $extract .] 0] _] end]"

puts $extract
Vishwadeep Singh
  • 1,043
  • 1
  • 13
  • 38
0

Only regexp is enough to do the trick.

Set string "xxxxxxx-s12345ab7_0_0_xx2.log"

regexp {(ab)(.*)_(.*)_(.*)_(.*)\\.} $string -> s1 s2 s3 s4 s5

Set rstring "$s1$s2$s3$s4\_$s5"

Puts $rstring

Patrick Kostjens
  • 5,065
  • 6
  • 29
  • 46
Joe
  • 1