Dan George
9/19/2007 9:21:00 PM
On Sep 19, 11:03 pm, Stefano Crocco <stefano.cro...@alice.it> wrote:
> Alle mercoled? 19 settembre 2007, Dan George ha scritto:
>
>
>
> > On Sep 19, 9:22 pm, Stefano Crocco <stefano.cro...@alice.it> wrote:
> > > Alle mercoled? 19 settembre 2007, Dan George ha scritto:
> > > > On Sep 19, 5:27 pm, Stefano Crocco <stefano.cro...@alice.it> 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 :).
>
> There's nothing obvious in the problem you're having (at least, not obvious
> for me). If, as you say, match is nil, it means that the trouble is outside
> the yaml file (which is only used in the following line). So, either the data
> doesn't have the expected format or the regexp isn't doing what I think it
> should. Yet, trying in irb, the regexp matched the line you posted. I'm at a
> loss, here. The best suggestion I can give you is to try putting a
> p lines[i-1]
> before the match line and see if this gives some insight on what it's
> happening.
>
> Stefano
First of all thanks for all your help so far.
I just don't get it.. the output looks like this:
"CATEG: CITY=0;STATE=0;\n"
nil
"CATEG: CITY=0;STATE=0;\n"
nil
and so on for all files.
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.