From: Stefano Crocco Date: 2007-09-20T07:41:41+09:00 Subject: Re: YAML & readlines & modify text files Alle gioved� 20 settembre 2007, Dan George ha scritto: > On Sep 20, 12:39 am, Stefano Crocco wrote: > > Alle mercoled� 19 settembre 2007, Dan George ha scritto: > > > CATEG being another line inside the text files... and the problem > > > might be because the Name-line isn't always above the Link-line. I > > > could have n lines between or below, what I'm trying to say is that I > > > don't know where the Name-line is inside the texts files. > > > > This changes everything. I assumed (according to the example lines you > > posted) that each Link-line had the corresponding Name-line above it. > > But, if there isn't a relation between the position of the two kind of > > lines, how can you know what to put in the link line? I mean, what is the > > relation which connects a Link-line and the corresponding Name-line? > > Since (from what you say now) the position of the two kind of lines are > > random (as far as this problem is concerned, at any rate) are you able, > > given a single Link-line, to understand which is the corresponding > > Name-line? If yes, how? Whithout knowing this, I can't help you. > > > > Stefano > > All I can say is that in each text file there will only be one Name- > line and one Link-line. The only connection between this 2 lines is > that the Link uses the shorter version of what is written in the Name- > line (i.e. if the Name-line: New York the Link line will use NY) > > Isn't it possible to read the Name-line, take the correspond value > from the YAML file, store it in a variable (string?) inside the code > and then use it in the Link-line, when going to the next text file > read again the Name-line and take the value from YAML and so on... If each file contains only one Name-line and one instance of the corresponding Link-line, this should work: require 'yaml' lnk='blabla.something.' op = '&=bla' hash = File.open('name.yaml'){|f| YAML.load f} Dir.glob('**/*.txt').each do |f| lines = File.readlines f name = nil link_idx = nil lines.each_with_index do |l, i| if l.match(/Name-line:\s+(.*)$/) then name $1 elsif l.match(/Link-line/) then link = i end break if name and link_idx end if name rep = hash[name] if rep lines[link_idx]="Link-line: #{lnk}#{rep}#{op}" File.open(f, 'w'){|of| of.write lines} else puts "name.yaml doesn't contain an entry for #{name} (file #{f})" end else puts "Couldn't find a Name line in file #{f}" end end For each file, it loops each line looking for a Name-line or a Link-line. When it finds the former, it stores the name in the name variable; when it finds the latter, it stores its index in the link_idx variable. When both are found, the loop stops (no point in examining the remaining lines). If a name has been found and it corresponds to an entry in the hash, the line with index link_idx is replaced with a new one (I removed the call to gsub!, since we're rebuilding the entire line, but you can put it back, if you need it), then the array is written to the file. If the Name-line wasn't found, or if the hash doesn't contain an entry for it, an error message is printed on screen and the next file is processed. I hope this helps Stefano