Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

another newbie question, simple string operation?

0 views
Skip to first unread message

Mark Morgan

unread,
Dec 19, 2009, 5:20:16 PM12/19/09
to
Hi again,
I think I've got a pretty straightforward question. I have a text
file called main.txt (several hundred lines of text) and in it is
smattered the occasional string which is a filename ending in
".txt" (another text file). The actual file, is in the same directory
and has no spaces, so that's ok.

What would be the best way to read in the main.txt file and substitute
the contents of each text file for the actual string of the text
file's name?

I'm guessing I should go line by line through main.txt looking for the
phrase ".txt" back up until the first space to get the name and then
map the text of the file onto the filename.

Is there any example of this anywhere else or is there a better way to
do a search and replace through a text file?

Thank you for any help.

Mark

Aric Bills

unread,
Dec 19, 2009, 6:47:43 PM12/19/09
to

You could do it like this (untested):

# read in main.txt
set file [open main.txt]
set data [read $file]
close $file

set map [list]

# look for all substrings containing no spaces and ending in .txt
foreach filename [regexp -all -inline {\S*\.txt} $data] {
# check whether the file exists
if {[file exists $filename]} {
# read in the contents of the file; add them to the map
set file [open $filename]
set contents [read $file]
close $file
lappend map $filename $contents
}
}

# perform the mapping
set newdata [string map $map $data]

For this to work properly, your working directory would have to be the
one where main.txt resides. To be safe, you should probably also sort
$map so that longer filenames come first (if you had a file file.txt
and another one called otherfile.txt and file.txt is earlier in the
list, it will get substituted first; every instance of otherfile.txt
will be changed to other<contents of file.txt>). In 8.6, you could
sort the list like this (also untested):

proc sortbylength {a b} {
return [expr {[string length $a] - [string length $b]}]
}

set map [lsort -index 0 -stride 2 -decreasing -command sortbylength
$map]

Hope that helps.

-Aric

Aric Bills

unread,
Dec 19, 2009, 10:09:35 PM12/19/09
to

Just realized that the code I provided may create duplicate entries in
the map. To fix that, replace this line:

foreach filename [regexp -all -inline {\S*\.txt} $data] {

with these:

foreach filename [lsort -unique \
[regexp -all -inline {\S*\.txt} $data]] {

Mark Morgan

unread,
Dec 21, 2009, 7:08:49 AM12/21/09
to
First of all, thank you for the help! The problem (and my solution)
have evolved over the last few days, but I used your suggestions to
start. I'm going to start a new post because of the significant
changes and the new questions I have.

Thank you again! Please take a look at my next post to see where this
ended up and what my new problem is. I'll put the code in that post,
as well.

Sincerely,
Mark

0 new messages