From: Stefano Crocco Date: 2007-09-20T17:51:53+09:00 Subject: Re: YAML & readlines & modify text files Alle gioved� 20 settembre 2007, Dan George ha scritto: > On Sep 20, 1:41 am, Stefano Crocco wrote: > > 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 > > Thanks for your reply Stefano! > > I had to do: > link_idx = nil.to_i > otherwise I would get this error: `[]': no implicit conversion from > nil to integer (TypeError) > > And it seems to be working but if I use this: > lines[link_idx]="Link-line: #{lnk}#{rep}#{op}" > the Name-line is removed and is replaced by the "Link-line: > #{lnk}#{rep}#{op}" but the old Link-line = 0 is kept too. > > If I use > lines[link_idx].gsub!(/Link-line.*/, 'Link-line: '+lnk+rep > +op) > nothing happends, no errors, no modified files, no nothing. > > I don't see anything wrong with the gsub! so what might be the problem? Another couple of mistakes on my part, I'm afraid. 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| #added missing = between name and $1 if l.match(/Name-line:\s+(.*)$/) then name = $1 #changed link = i to link_idx = i elsif l.match(/Link-line/) then link_idx = i end break if name and link_idx end #checking that also link_idx is not nil if name and link_idx 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 the name #{name}" end #changed the error message else puts "Name or Link line are missing in file #{f}" end end Stefano