user14537238
user14537238

Reputation: 21

How to match a string and print the next word afterthat?

Lets say i have the following script and have to look for .model and print the next two word before (. The following is the contents of the file that I need to read.

    .model Q2N2222  NPN(Is=14.34f Xti=3 Eg=1.11 Vaf=74.03 Bf=255.9 Ne=1.307
                        Ise=14.34f Ikf=.2847 Xtb=1.5 Br=6.092 Nc=2 Isc=0 Ikr=0 Rc=1
+       Cjc=7.306p Mjc=.3416 Vjc=.75 Fc=.5 Cje=22.01p Mje=.377 Vje=.75
+       Tr=46.91n Tf=411.1p Itf=.6 Vtf=1.7 Xtf=3 Rb=10)
*       National    pid=19      case=TO18
*       88-09-07 bam    creation
*$
    .model Q2N3904  NPN(Is=6.734f Xti=3 Eg=1.11 Vaf=74.03 Bf=416.4 Ne=1.259
    .model Q2N3906  PNP(Is=1.41f Xti=3 Eg=1.11 Vaf=18.7 Bf=180.7 Ne=1.5 Ise=0

Here is the code i have written so far. But i couldnt get any. Need the help

proc find_lib_parts {f_name} {
    set value [string first ".lib" $f_name]
    if {$value != -1} {
        #open the file
        set fid [ open $f_name "r"]

        #read the fid and split it in to lines
        set infos [split [read $fid] "\n"]
        close $fid

        set res {}
        append res "MODEL FOUND:\n"
    
        if {[llength $line] > 2 && [lindex $line 0] eq {model}} {
            #lappend res [lindex $data 2] \n 
            lappend res [split $line "("]\n
        } 
        if {[llength $line] > 2 && [lindex $line 0] eq {MODEL}} {
            #lappend res [lindex $data 2] \n 
            lappend res [split $line "("]\n
        }
    }

    return $res

Upvotes: 1

Views: 787

Answers (1)

Donal Fellows
Donal Fellows

Reputation: 137567

In this case, a regular expression is by far the simplest way of doing such a search. Assuming the words are always on the same line, it's easy:

proc find_lib_parts {f_name} {
    set fid [open $f_name]
    set infos [split [read $fid] "\n"]
    close $fid

    set found {}
    foreach line $infos {
        if {[regexp {\.model\s+(\w+\s+\w+)\(} $line -> twoWords]} {
            lappend found $twoWords
        }
    }
    return $found
}

For your input data sample, that'll produce a result like this:

{Q2N2222  NPN} {Q2N3904  NPN} {Q2N3906  PNP}

If there's nothing to find, you'll get an empty list. (I assume you pass filenames correctly anyway, so I omitted that check.)


The regular expression, which should virtually always be enclosed in {braces} in Tcl, is this:

\.model\s+(\w+\s+\w+)\(

It's relatively simple. The pieces of it are:

  1. \.model — literal “.model” (with an escape of the . because it is a RE metacharacter)
  2. \s+ — some whitespace
  3. ( — start a capturing group (the bit we put into the twoWords variable)
  4. \w+ — a “word”, one or more alphanumeric (or underscore) characters
  5. \s+ — some whitespace
  6. \w+ — a “word”, one or more alphanumeric (or underscore) characters
  7. ) — end of the capturing group
  8. \( — literal “(”, escaped

The regexp command matches this, returning whether or not it matched (effectively boolean without the -all option, which we're not using here), and assigning the various groups to the variables named afterwards, -> for the whole matched string (yes, that's a legal variable name; I like to use it for regexp variables that dump info I don't want) and twoWords for the interesting substring.

Upvotes: 1

Related Questions