Reza
Reza

Reputation: 19

Finding a word in a string in tcl

I have this string:

1, RotD50, 88, 0.1582, 1.2264, -, 7.4, 23.6, 0.2, "San Fernando", 1971, "Santa Felita Dam (Outlet)", 6.61, Reverse, 24.69, 24.87, 389.0, 0.125, 1.2939, RSN88_SFERN_FSD172.AT2, RSN88_SFERN_FSD262.AT2 , RSN88_SFERN_FSD-UP.AT2

I want to find the indices of RSN88_SFERN_FSD172.AT2 and RSN88_SFERN_FSD262.AT2

I have tried a few scripts (like the following) but want to see if someone can help me with a rigorous script?

set currentdirc  [pwd]
set  fp  [open  _SearchResults.csv]
set count 1

foreach line [split [read $fp] \n] {
    foreach word [split  $line] {
        set word [string  trim  $word ","]
        set index  [lsearch -exact  $word  "Horizontal-1 Acc.Filename"]
        puts "$index"
    }
}

Upvotes: 1

Views: 4218

Answers (2)

Peter Lewerin
Peter Lewerin

Reputation: 13252

You are going to need this:

package require csv

As before, break the data into lines and iterate over those lines. Trim the data first to avoid empty lines before or after.

foreach line [split [string trim [read $fp]] \n] {

Instead of trying to split the csv data using the split command, use the dedicated command ::csv::split from the csv package in Tcllib. You probably have it in your Tcl installation already.

    set words [::csv::split $line]

When your line is split, there is unwanted whitespace around many data fields. Let's trim it off.

    set words [lmap word $words {string trim $word}]

Finally, you can search for data in the list of words. Searching in each word as you did is pointless.

    set index [lsearch $words RSN88_SFERN_FSD262.AT2]

Putting it together:

foreach line [split [string trim [read $fp]] \n] {
    set words [::csv::split $line]
    set words [lmap word $words {string trim $word}]
    set index [lsearch $words RSN88_SFERN_FSD262.AT2]
    puts $index
}

Documentation: csv (package), foreach, lmap (for Tcl 8.5), lmap, lsearch, package, puts, read, set, split, string

Upvotes: 2

Jerry
Jerry

Reputation: 71538

I would use the csv package to do that task, since you are dealing with a csv file. Splitting blindly will split 1, RotD50, 88, 0.1582, 1.2264, -, 7.4, 23.6, 0.2, "San Fernando" things into, for example (each element on their own line):

1,
RotD50,
88,
0.1582,
1.2264,
-,
7.4,
23.6,
0.2,
"San
Fernando"

So my suggestion is:

set currentdirc [pwd]
set fp [open [file join $currentdirc _SearchResults.csv] r]

package require csv
foreach line [split [read $fp] \n] {
    set words [::csv::split $line]
    set index [lsearch -exact $words "Horizontal-1 Acc.Filename"]
    puts $index
}

Also the list of words is the whole line. So if you want to loop through the words, you would do if {$word eq "Horizontal-1 Acc.Filename"} instead and you would have to use count (that I removed in my suggestion) to keep track of the index.

If for some reason you cannot use the csv package, you can try using this instead of the line containing ::csv::split:

set all [regexp -all -inline -- {\"[^\"]+\"|[^,]+} $line]
set words [lmap w $all {set w [string trim $w {\" }]}]

(I'm using \" for the quotes only for the sake of proper syntax highlighting, you can safely use " alone)

Upvotes: 1

Related Questions