From: Mark Morgan on
>Starting out by trying to understand the requirements here. You have a
>file whose contents includes sequences of the form:
> {@INPUTFILE FOOBAR.txt}
>and each of those sequences needs to be replaced by the contents of
>the file with the given name?

That's correct. I really appreciate the input. As you might be able
to tell this isn't my day job. :)
I'll be able to give it a whirl later on and I'll send an even more
grateful thank you email then!

Thank you for your answer!
Take care,
Mark
From: Donald Arseneau on
On Dec 21, 4:28 am, Mark Morgan <me.mor...(a)yahoo.com> wrote:
> My basic issue is I've got a master text file that has the text of
> other filenames scattered in it.  I'm trying to substitute the
> contents of the other files into the place where the filename is in
> the master text file.  Everything is in the same directory.
>
> The filename and the surrounding text that will need to be replaced is
> this (quoted):  "{@INPUTFILE example.txt}".  The problem I'm having is
> that I can't get it to substitute all of that text, all of the time.
> Specifically if the file example.txt contains (quoted): "Example:
> 300-45823" then it won't replace it.  If it has "{Example:  300-45823}
> then it will.

>     foreach textspiel [regexp -all -inline \
> {((\{@INPUTFILE)\s+\w+(.txt\}))} $data] {

That doesn't make sense. The regexp is returning
quadruplets of matches: the whole match, the outer ()
and the two inner (), so you should be skipping through
the list 4 at a time (foreach {a b c d} [regexp..).
I also see you have "." used where you intend "\."
to match a literal period, not any one character.
You aren't doing anything useful with the parentheses,
so I suspect you misunderstand their function. Instead
you should probably have used

foreach {textspiel textfilename} [regexp -all -inline \
{\{@INPUTFILE\s+(\w+\.txt)\s+\}} $data] {

> But, I think it must have to do with the brackets. It seems like when
> the text file that's going to be substituted into the master file
> contains bracketed text then the substitution goes forward. If not,
> regexp finds it and sends it down through the code but regsub won't
> substitute it.

Yes, you suspect correctly (but your demonstration didn't
even get that far).

>                 regsub -all {$textspiel} $data {$contents} data;

Here you are using literal plain text $textspiel as a
regular expression meaning match the end of a line followed
by "textspiel". Of course you meant "$textspiel" or $textspiel
so that the value of the variable was used. But in that case
you are still using plain (uncontrolled) text as a regular
expression, which it is not. There are three solutions for
that:

1) Don't use regsub: use string map instead.

2) Put escapes (backslashes) in front of all special charcters
in the $textspiel text, using string map. Check re_syntax to
make sure you cover every character that is special to regexp.

3) Tell regexp that the string is literal:
regsub "***=$textspiel" $data {$contents} data

Probably 1) is the best, but 3) is also convenient (but harder
to decipher when you see the program later).

(There is no reason to use -all because you are doing one
item at a time with the foreach loop.)


Donald Arseneau
From: Mark Morgan on
>   proc processTemplate string {
>       # This is exactly the replacement to make a string [subst]-safe
>       set s [string map {$ \\$ \[ \\\[ \\ \\\\} $string]
>       # Now convert the replacements to embedded commands
>       regsub -all {{@INPUTFILE (\w+\.txt)}} $s {[readFromFile \1]} s
>       # Process all the substitutions
>       return [subst $s]
>   }
>   # Simple read-a-file helper
>   proc readFromFile filename {
>       set f [open $filename]
>       set d [read $f]
>       close $f
>       return $d
>       # Use this instead if you want recursive template processing:
>       #    return [processTemplate $d]
>   }

OK, I've had some time to try to figure out what is happening here. I
didn't have enough time to get it fully working but that's because of
my data, I'm sure. I really, really appreciate ALL of the suggestions
and posts. This is really helpful! I'm basically trying to prepare
data in a TCL based program for use in a simple web app. This piece
has been holding me up for quite a while. I can't tell you how nice
it is to be so close to getting this part done!!!

I'll get another chance tonight (hopefully) to work on this.

#1 I figured I'd push my luck and ask if there's any simple way to
catch the problem (common in my data) that the file (that comes after
"@INPUTFILE") is missing. I was thinking that it'd be nice to
substitute in some little note in the text file. My previous code had
a little phrase that got put in there.

#2 You can tell I didn't get too far, but would this be the proper
implementation of the code you have written:

set file [open $filename r+]
set data [read $file]
processTemplate $data
puts $file $data
close $file

#3 I've got to get to my day job. I can't wait to get back to this,
though!

Take care,
Mark
From: Donald Arseneau on
On Dec 21, 4:37 pm, Donald Arseneau <a...(a)triumf.ca> wrote:
> 3) Tell regexp that the string is literal:
>    regsub "***=$textspiel" $data {$contents} data

I know you are on a track with [string map] followed by
[eval], which is good. But for posterity I had better
fix the bug above: I retained some other bogus braces
from your original. It should be

regsub "***=$textspiel" $data $contents data

Donald Arseneau
From: slebetman on
On Dec 22, 8:24 pm, Mark Morgan <admin.shortst...(a)gmail.com> wrote:
> <snip>
>
> #2 You can tell I didn't get too far, but would this be the proper
> implementation of the code you have written:
>
>   set file [open $filename r+]
>   set data [read $file]
>   processTemplate $data
>   puts $file $data
>   close $file
>

close. If your intention is to append the processed text to the end of
the unprocessed text then what you're doing is perfect. If on the
other hand you intend to replace the unprocessed text with the
processed text then you should seek to beginning of file:

...
set data [processTemplate $data]
seek $file 0
puts $file $data
...
First  |  Prev  |  Next  |  Last
Pages: 1 2 3 4
Prev: Silent wrapping
Next: tcl on multicore, what is the plan