Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Ruby > Sed -> Ruby : .. and ...

Reply
Thread Tools

Sed -> Ruby : .. and ...

 
 
Keith Fahlgren
Guest
Posts: n/a
 
      07-28-2005
Hi all,

What's the deal with all the different versions of
http://pleac.sourceforge.net/pleac_r...nmatching.html on the
web? I've found that the most complete document and most helpful on
this sort of Ruby regular expression tutelage.

It seems like documentation on adopting sed to Ruby would be helpful.
[I'll write something if I ever understand it.]

Surprise: I'm trying to adapt some sed scripts into Ruby programs. I'd
like feedback on how to make them more idiomatic/Rubylicious and help
on making 2nd one work.

Here's my essential program for a line of sed that seems to work
correctly. I dunno if there's a better way to express it:

---------------------------------------------------

sed:
s/MATCH/GLOBAL REPLACEMENT/g

ruby:
#!/usr/bin/env ruby

files = ARGV

files.each do |arg|
f = File.open(arg)
puts "\nOpening file #{f}"
working_file = f.read

working_file.gsub!(/MATCH/,'GLOBAL REPLACEMENT')

puts "\nDoing ACTION in #{arg}"
f = File.new(arg, "w")
puts "\nWriting #{f} now"
f.print(working_file)
f.close
end

---------------------------------------------------

Here's the one I have problems with (we had a working Perl equivalent
but are trying to abandon Perl).

sed:
/BEGIN RANGE/,/END RANGE/{
s/MATCH/REPLACEMENT/g
}

ruby:
[same beginning]
if working_file =~ /BEGIN RANGE/ .. working_file =~ /END RANGE/
# INCLUSIVE use ... if you want non inclusive
working_file.sub!(/MATCH/,'REPLACEMENT')
end
[same ending]
-----------------

The above works fine on the first occurence of MATCH but won't do any of
the subsequent matches in the document. I subsitute 'gsub' but that
will just effect all of the places in the document, ignoring my if
statement. Suspecting a lack of understanding of the way the range
works and find and old thread on the mailing list
( http://blade.nagaokaut.ac.jp/cgi-bin...uby-talk/73674 )
but don't really follow it.

I've come up with the following as a tentative replacement but it's not
setting 'aline' in 'working_file' after it substitues it.

[same beginning]
working_file.each do |aline| # Read each line, right?
if aline =~ /BEGIN RANGE/ .. aline =~ /# end of CellContent/
aline.sub!(/Cell/,'CellHeading2')
end
end
[same ending]
-----------------

[Running up against my own ignorance now of the range thingie]
Here's my failing test:
#!/usr/bin/env ruby
files = ARGV
files.each do |arg|
f = File.open(arg)
puts "\nOpening file #{f}"
working_file = f.read
puts "Subsitutions occuring now"
working_file.each do |aline|
if aline =~ /BEGIN RANGE/ .. aline =~ /END RANGE/
aline.sub!(/MATCH/,'REPLACEMENT')
puts "#{aline}"
end
end
puts "\nOutput of working_file"
puts "#{working_file}"
puts "\nDoing ACTION in #{arg}"
f = File.new(arg, "w")
puts "\nWriting #{f} now"
f.print(working_file)
f.close
end

-----------------
Here's the test file:
a lonely line
BEGIN RANGE
MATCH
END RANGE
another lonely line
BEGIN RANGE
MATCH
nothing here
MATCH
END RANGE
don't change MATCH

-----------------
Here's the output:
> ,rtest2 ,test.txt


Opening file #<File:0xff3f0>
Subsitutions occuring now
BEGIN RANGE
REPLACEMENT
END RANGE
BEGIN RANGE
REPLACEMENT
nothing here
REPLACEMENT
END RANGE

Output of working_file
a lonely line
BEGIN RANGE
MATCH
END RANGE
another lonely line
BEGIN RANGE
MATCH
nothing here
MATCH
END RANGE
don't change MATCH



Doing ACTION in ,test.txt

Writing #<File:0xfeef8> now


Thanks for your help,
Keith


 
Reply With Quote
 
 
 
 
Joel VanderWerf
Guest
Posts: n/a
 
      07-28-2005
Keith Fahlgren wrote:
> sed:
> s/MATCH/GLOBAL REPLACEMENT/g
>
> ruby:


$ cat test
foo
bar
123
$ ruby -p -e 'gsub(/bar/, "BAR")' test
foo
BAR
123

Also, you can use the ARGF constant to access all of the input files (or
stdin if there are none) as a single IO.

ARGF.each do |line|
...
end


 
Reply With Quote
 
 
 
 
Keith Fahlgren
Guest
Posts: n/a
 
      07-28-2005
On Thursday 28 July 2005 11:25 am, Joel VanderWerf wrote:
> $ ruby -p -e 'gsub(/bar/, "BAR")' test


Ah, I should have mentioned that I'm trying to replace 4000+ lines of
sed rather than just one. So, the one-liner approach is probably not
the best in this case.


Thanks for the reminder on ARGF.each,
Keith


 
Reply With Quote
 
William James
Guest
Posts: n/a
 
      07-28-2005


Keith Fahlgren wrote:

> Here's the one I have problems with (we had a working Perl equivalent
> but are trying to abandon Perl).
>
> sed:
> /BEGIN RANGE/,/END RANGE/{
> s/MATCH/REPLACEMENT/g
> }
>
> ruby:
> [same beginning]
> if working_file =~ /BEGIN RANGE/ .. working_file =~ /END RANGE/
> # INCLUSIVE use ... if you want non inclusive
> working_file.sub!(/MATCH/,'REPLACEMENT')
> end
> [same ending]


ruby -pe 'gsub(/e/, "-") if $_ =~ /START/ .. $_ =~ /END/' infile
>outfile


 
Reply With Quote
 
William James
Guest
Posts: n/a
 
      07-29-2005
Keith Fahlgren wrote:

> sed:
> s/MATCH/GLOBAL REPLACEMENT/g
>
> ruby:
> #!/usr/bin/env ruby
>
> files = ARGV
>
> files.each do |arg|
> f = File.open(arg)
> puts "\nOpening file #{f}"
> working_file = f.read
>
> working_file.gsub!(/MATCH/,'GLOBAL REPLACEMENT')
>
> puts "\nDoing ACTION in #{arg}"
> f = File.new(arg, "w")
> puts "\nWriting #{f} now"
> f.print(working_file)
> f.close
> end


Let Ruby change the file "in place". A backup file with ".bak"
appended to the filename will be created.

#! ruby -i.bak -pl
gsub(/MATCH/,"REPLACEMENT")

 
Reply With Quote
 
Keith Fahlgren
Guest
Posts: n/a
 
      07-29-2005
Hi all,

Thanks for the helpful responses. Many corrected me, rightly, for
writing a whole program rather than just using a one-liner and for
modifying the file in place rather than setting up temporary files. I
was concentrating on my task, making a template to replace thousands of
lines of sed files rather than doing a single replacement.

My larger problem still revolved around doing a bunch matches inside an
range.

On Thursday 28 July 2005 5:46 pm, mathew wrote:
> working_file.gsub!(/(?=BEGIN RANGE)(.*?)(?=END RANGE)/m) {||
> $1.gsub(/MATCH/m, 'REPLACEMENT')
> }


Matthew pointed out an easier way to get around it but I had rejected
that method from the start because I wanted to be able to nest ranges
(like I can in sed).

I think the problems with my inital attempts was assuming .read was
returning an array rather than a string. Slapping .to_a to the end
solved that bit and the program now works as expected, I think.

Here's my solution (though I'd still love comments):


#!/usr/bin/env ruby
files = ARGV

files.each do |arg|
puts "\nOpening file #{arg}"
f = File.open(arg)
working_file = f.read.to_a
f.close
working_file.each do |aline|
if aline =~ /BEGIN RANGE/ .. aline =~ /END RANGE/
#nest if lines like above as many times as needed for nested
ranges
aline.sub!(/MATCH/,'REPLACEMENT')
end
end

puts "\nDoing ACTION in #{arg}"
fnew = File.new("#{arg}.tmp", "w")
puts "\nWriting #{fnew} now"
fnew.print(working_file)
fnew.close
end



Thanks,
Keith


 
Reply With Quote
 
Brian Schröder
Guest
Posts: n/a
 
      07-29-2005
On 29/07/05, Keith Fahlgren <(E-Mail Removed)> wrote:
> Hi all,
>=20
> Thanks for the helpful responses. Many corrected me, rightly, for
> writing a whole program rather than just using a one-liner and for
> modifying the file in place rather than setting up temporary files. I
> was concentrating on my task, making a template to replace thousands of
> lines of sed files rather than doing a single replacement.
>=20
> My larger problem still revolved around doing a bunch matches inside an
> range.
>=20
> On Thursday 28 July 2005 5:46 pm, mathew wrote:
> > working_file.gsub!(/(?=3DBEGIN RANGE)(.*?)(?=3DEND RANGE)/m) {||
> > $1.gsub(/MATCH/m, 'REPLACEMENT')
> > }

>=20
> Matthew pointed out an easier way to get around it but I had rejected
> that method from the start because I wanted to be able to nest ranges
> (like I can in sed).
>=20
> I think the problems with my inital attempts was assuming .read was
> returning an array rather than a string. Slapping .to_a to the end
> solved that bit and the program now works as expected, I think.
>=20
> Here's my solution (though I'd still love comments):
>=20
>=20
> #!/usr/bin/env ruby
> files =3D ARGV
>=20
> files.each do |arg|
> puts "\nOpening file #{arg}"
> f =3D File.open(arg)
> working_file =3D f.read.to_a
> f.close
> working_file.each do |aline|
> if aline =3D~ /BEGIN RANGE/ .. aline =3D~ /END RANGE/
> #nest if lines like above as many times as needed for nested
> ranges
> aline.sub!(/MATCH/,'REPLACEMENT')
> end
> end
>=20
> puts "\nDoing ACTION in #{arg}"
> fnew =3D File.new("#{arg}.tmp", "w")
> puts "\nWriting #{fnew} now"
> fnew.print(working_file)
> fnew.close
> end
>=20
>=20
>=20
> Thanks,
> Keith
>=20
>=20


My approach would be something along these lines:

bschroed@black:~/svn/projekte/ruby-things$ cat test
test
Range1
test1
Range2
test2
EndRange2
test3
EndRange1
bschroed@black:~/svn/projekte/ruby-things$ cat ranges.rb
ARGV.each do | filename |
result =3D []
File.read(filename).split("\n").each do | line |
if line =3D~ /^Range1/ .. line =3D~ /^EndRange1/
if line =3D~ /^Range2/ .. line =3D~ /^EndRange2/
result << " - " + line
else
result << " - " + line
end
else
result << "- " + line
end
end

puts filename
puts "-" * filename.length
puts result
puts "-" * filename.length
puts
end

bschroed@black:~/svn/projekte/ruby-things$ ruby ranges.rb test
test
----
- test
- Range1
- test1
- Range2
- test2
- EndRange2
- test3
- EndRange1
----

regards,

Brian


--=20
http://ruby.brian-schroeder.de/

Stringed instrument chords: http://chordlist.brian-schroeder.de/


 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Right tool and method to strip off html files (python, sed, awk?) sebzzz@gmail.com Python 5 07-16-2007 03:01 AM
add blank lines after word MAC (sed/awk or perl??) NNTP Perl 2 04-07-2004 06:04 AM
using perl on the command line, like sed or awk gorda Perl 2 10-21-2003 06:38 AM
sed awk or perl for this? NNTP Perl 13 09-30-2003 06:49 AM
sed regexp mystery John K. Humkey Perl 0 07-08-2003 03:55 AM



Advertisments