From: Dan George Date: 2007-09-20T04:35:09+09:00 Subject: Re: YAML & readlines & modify text files On Sep 19, 9:22 pm, Stefano Crocco wrote: > Alle mercoled� 19 settembre 2007, Dan George ha scritto: > > > > > On Sep 19, 5:27 pm, Stefano Crocco wrote: > > > Alle mercoled� 19 settembre 2007, Dan George ha scritto: > > > > I'm not at all sure I understand correctly what you want to do. I think > > > you want to replace the line under > > > > Name-line: Name01 > > > > with some text containing a string taken from the Name01 entry in the > > > yaml file. Is it correct? If it isn't, then please explain better what > > > you mean. Otherwise, read on. > > > > In my opinion, you're storing data in the YAML file in the wrong way, > > > because, at each iteration, name contains only one pair of > > > name/replacement string, which forces you to iterate over all the files > > > for each document in the YAML file (and also makes the replacing code > > > more complicated). I think your YAML file should contain a single hash, > > > with the names as keys and the replacement strings as values: > > > > --- > > > Name01: N01 > > > Name02: N02 > > > > Then, you can do the following (untested) > > > > require 'yaml' > > > lnk = 'blabla.something.' > > > op = '&=bla' > > > hash = File.open('name.yaml'){|f| YAML.load f} > > > Dir.glob('**/.txt').each do |path| > > > lines = File.readlines(path) > > > lines.each_with_index do |line, i| > > > if line.match(/Link-line/) > > > match = lines[i-1].match(/Name-line:\s(.*)$/)[1] > > > line.gsub!(/Link-line.*/, 'Link-line: '+ lnk+hash[match[1]]+ > > > op) if match and hash.has_key?(match[1]) > > > end > > > end > > > File.open(path,'w'){|f| f.write lines} > > > end > > > > When iterating on the lines, the block is passed not only the line, but > > > also the line number. This way, when you meet a Link-line line, you can > > > access the corresponding name-line using its index. It then matches the > > > previous line with a regexp to extract the name from it and stores the > > > result in the match variable. If match is not nil (i.e if the name line > > > had the expected format) and the name is included in hash, the > > > replacement is performed (of course, you can skip this test if you're > > > confident enough in the format of the files and in the contents of the > > > yaml file) > > > > I hope this helps > > > > Stefano > > > You are correct, that is what I want! > > > I tryied what you suggested but I get some weird errors: > > > new.rb:45: undefined method `[]' for nil:NilClass (NoMethodError) > > from D:/ruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in > > `each_with_index' > > from new.rb:43:in `each' > > from new.rb:43:in `each_with_index' > > from new.rb:43 > > from new.rb:41:in `each' > > from new.rb:41 > > > Line 45 is: match = lines[i-1].match(/Name-line:\s(.*)$/)[1] > > Line 43 is: lines.each_with_index do |line, i| > > Line 41 is: Dir.glob('**/*.jad').each do |path| > > > I don't get it, as far as I can tell the code is ok... > > I think it's because of a mistake in my code: the [1] part of line 45 > shouldn't be there (it's a leftover from a previous version of the code). > If I'm right, the string doesn't match the regexp, so lines[i-1].match(...) > returns nil, which doesn't have a [] method, leading to the error you get. > Avod to call nil.[] is the reason for the conditional at the end of the > following line (note that the conditional checks that match is not nil before > trying to extract an element from it), but this is useless if I call it on > the line before. Removing that [1] from line 45 should solve your porblem. > > However, if you found this mistake, it may mean that there's something amiss > in either your .txt files or your yaml file (see the end of my previous > post). > > Stefano Stefano thanks for your replies so far. That did. The code executes ok but "match = lines[i-1].match(/Name- line:\s(.*)$/)" always returs nil (I did "puts match" after it) and I don't understand why. I checked my txt files and my yaml file and they are ok. txt file has: Name-line: New York Link-line: etc and YAML file has: --- New York: NY So the value from the Name is equal to the one in the YAML file. Am I still missing something obvious? Sorry if some things seem so obvious that I should understand them but I'm just a beginner, started a couple of weeks back and the only way for me to learn is from examples that I try myself and it annoys to see that something simple gives me so much trouble but I don't want to quit either :).