2

I have a file named ama.txt and the content of the file is like this:

name      age   hobby       sex

amit      45    music       male

sumit     35    cricket     female

Now I can open the file like this:

File.open("ama.txt").each do

end

How can I modify the hobby column of the file?

Telemachus
  • 19,459
  • 7
  • 57
  • 79
Milan
  • 1,447
  • 5
  • 19
  • 27

2 Answers2

16

The general pattern for something like this is roughly as follows:

  1. Open the original file for reading and a new file for writing. Read the original line by line.
  2. Skip any lines that aren't relevant (you want to skip your header line and the blanks, for example)
  3. Deal with the individual lines however you need. Here you probably want something like cols = line.split(/\s+/) and then you want to edit cols[2], though I don't know if the changes fit a pattern or what.
  4. Once you have the edits made, print the edited line out to the new file.
  5. Once you're done with reading the original and writing the changed lines to the new file, close both files.
  6. Change the original's name to something like 'original_name' + '.bak' and the new file's name to 'original_name'.
  7. Done.

Ruby, like most scripting languages, has a lot of built-in ways to make some of these steps go quicker, but that's the basic pattern. Dmitry is potentially right that a CSV reader would help you here, but I can't see how well-formatted (or not) your data is, so I'm not even going to get into that.

Finally, and not to be rude, but it doesn't seem that you know Ruby especially well. Why is Ruby a requirement? Do you know another scripting language? How well do you know Ruby? In general, people here will help you with things, but not simply write code for you.

To answer Amit's question about step 4: If you have a new file open for writing, you will have a filehandle - a variable in your program pointing to the open file. You can write to that file by using the filehandle as a receiver for puts. This looks weird at first, since puts looks like a function normally, but it is a method call in Ruby. Try this in irb or a short Ruby script:

fh = File.open('test.txt', 'w')
fh.puts "hello, world"
fh.close

Another short example:

#!/usr/bin/env ruby
out_file = File.open('output.txt', 'w')

File.open('input.txt', 'r').each do |line|
  out_file.print line.sub('foo', 'bar')
end

out_file.close
# no need to close the input file since the block version closes it for us
# automagically

# Maybe better to put the whole thing in a double block, though you may
# find this harder to follow at first
File.open('output.txt', 'w') do |out_file|
  File.open('input.txt', 'r').each do |line|
    out_file.print line.sub('foo', 'bar')
  end
end
Telemachus
  • 19,459
  • 7
  • 57
  • 79
  • thanks tele but could i get some code means what you wrote its implementation . yaa tele i just started ruby for my colleage project – Milan Jul 20 '10 at 13:54
  • yaa okk you are saying right noone write code for me thanks for your help – Milan Jul 20 '10 at 13:55
  • and tele what u said will not work either so next time come up something different – Milan Jul 20 '10 at 14:12
  • yaa tele that fh is file handle or object and i used it before but sumthing i wrote path="c:/put/ama12.txt" File.readlines(path).each do |$line| $row = $line.chomp.split('\t') # use your delimiter symbol $row[2] ="raman" end fh = File.open('test.txt', 'w') fh.puts $row fh.close but nothing happening for me – Milan Jul 21 '10 at 11:45
  • @amit Nothing happens because you're trying to do the writing _after_ you've already finished all the reading. Check my outline again. You open both files (the one you read from, and the one you will write to) _earlier_. Then, after you get each line from the one you read, you write it out to the other at the same time. I'll add an example above, but you really need to read your textbook or see your teacher. – Telemachus Jul 21 '10 at 11:58
  • When I tried your example, it did not seem to close the input file properly until it exited the script. So I split `File.open('input.txt', 'r').each do |line|` into two nested blocks: `File.open('input.txt', 'r') do |file|` with an inner `file.each do |line|` block and that worked as expected. – Mike Henry Feb 02 '12 at 08:47
1
File.readlines("ama.txt").each do |line|
  row = line.strip.split('\t') # use your delimiter symbol
  row[2] = ... # hobby column
end

Or just use fastercsv gem.

Dmitry Maksimov
  • 2,861
  • 24
  • 19
  • Dmitry i have to put this code in file.open("ama.txt).each do end ?? – Milan Jul 20 '10 at 13:01
  • Tele its not working i want to modify the values of hobby column how to do that?? – Milan Jul 20 '10 at 13:15
  • nd File.open is not returing array of line like when i tried to do like puts "#{line[0]}" i am not getting any value – Milan Jul 20 '10 at 13:17
  • and one more i wouls like to have these changes must be reflected in ama.txt file – Milan Jul 20 '10 at 13:32
  • I forgot each, just added it. – Dmitry Maksimov Jul 20 '10 at 17:54
  • path="c:/put/ama12.txt" path1="c:/put/ama1.txt" out_file = File.open(path1, 'w') x=0 File.open(path, 'r').each do |line| $row = line.chomp.split("\t") if(x==1) $row[0]="sdrom" line=$row puts end x=x+1 out_file.print "#{line}" end out_file.close – Milan Jul 22 '10 at 07:53
  • this is what i did but the problem i have is my output is like name age hobby sex sdrom45cricketmale the sencond line should be tab saprated how to do it tele?? – Milan Jul 22 '10 at 07:57