ruby equiv of perl pos

S

snacktime

Or to be more exact, how would I do the following in ruby?

while ($string =~ /\0/g) {
$new_string .= sprintf '\%o', (pos $string) - 1;
}
 
G

gga

snacktime ha escrito:
Or to be more exact, how would I do the following in ruby?

while ($string =~ /\0/g) {
$new_string .= sprintf '\%o', (pos $string) - 1;
}

#!/usr/bin/env ruby

new_string = ''
string = "\0\0\0asda\0\0\0sdasd"

pos = 0
while pos = string.index( /\0/, pos )
match = Regexp.last_match
pos += match.size
new_string << '\%o' % (pos - 1)
end

puts new_string
 
J

James Edward Gray II

$ ri -T IO#pos
----------------------------------------------------------------- IO#pos
ios.pos => integer
ios.tell => integer
------------------------------------------------------------------------
Returns the current offset (in bytes) of ios.

f = File.new("testfile")
f.pos #=> 0
f.gets #=> "This is line one\n"
f.pos #=> 17


James Edward Gray II
 
R

Robin Stocker

snacktime said:
Or to be more exact, how would I do the following in ruby?

while ($string =~ /\0/g) {
$new_string .= sprintf '\%o', (pos $string) - 1;
}

Another idea:

string = "one\0two\0threeeeeee\0"
result = ''
string.scan(/\0/) do
result << '\%o' % $`.length
end
puts result #=> \3\7\22

Robin
 
G

gga

Another idea:

string = "one\0two\0threeeeeee\0"
result = ''
string.scan(/\0/) do
result << '\%o' % $`.length
end

This is simpler to write, but will be slower on longer strings.

#!/usr/bin/env ruby

@string = "\0\0\0asda\0\0\0sdasd" * 5000

def test_a
result = ''
pos = 0
while pos = @string.index( /\0/, pos )
match = Regexp.last_match
pos += match.size
result << '\%o' % (pos - 1)
end
return result
end


def test_b
result = ''
@string.scan(/\0/) do
result << '\%o' % $`.length
end
return result
end

require 'benchmark'

Benchmark.benchmark() { |x|
x.report('a:') { test_a }
x.report('b:') { test_b }
}
 
R

Robin Stocker

gga said:
This is simpler to write, but will be slower on longer strings.

You're right, it's much slower! I didn't think about speed while writing
it, thanks for pointing it out.

Another question: Why do you use Regexp.last_match? Maybe to have a more
general solution? The following seems to be simpler and faster:

def test_b
result = ''
pos = 0
while pos = @string.index("\0", pos)
result << '\%o' % pos
pos += 1
end
return result
end
 
S

snacktime

Thanks guys. I'm having to write a module to set parity on strings.
I'll post it when I'm done, maybe someone can help clean it
up/refactor it a bit and put it on rubyforge or something. Not sure
how much demand there is for something like this.
 
L

Logan Capaldo

Or to be more exact, how would I do the following in ruby?

while ($string =~ /\0/g) {
$new_string .= sprintf '\%o', (pos $string) - 1;
}

if perldoc -f pos is describing what pos does in this case,

new_string = ""
while pos = string =~ /\0/g
new_string << "%o" % (pos - 1)
end
 
G

gga

Robin Stocker ha escrito:
Another question: Why do you use Regexp.last_match? Maybe to have a more
general solution?

Yes. That way you can use any sort of regexp, not just a single
character match.
 
G

gga

Logan Capaldo ha escrito:
if perldoc -f pos is describing what pos does in this case,

new_string = ""
while pos = string =~ /\0/g
new_string << "%o" % (pos - 1)
end

This won't work. Regexp in ruby does not support Perl's /g option.
You need to use String.index() with a position modifier as I showed
before or gsub in case of a global regexp replacement.
 
L

Logan Capaldo

Logan Capaldo ha escrito:


This won't work. Regexp in ruby does not support Perl's /g option.
You need to use String.index() with a position modifier as I showed
before or gsub in case of a global regexp replacement.

Oops, out of practice with my perl. Forgot that /g with a while loop
was how you did #scan { } in perl.

How about:

new_string = ""
string.scan(/\0/) do |m|
new_string = "%o" % $~.offset(0).first
end
 
G

gga

Logan Capaldo ha escrito:
How about:

new_string = ""
string.scan(/\0/) do |m|
new_string = "%o" % $~.offset(0).first
end

That should work okay (well, it should be new_string << ..., thou).
I'll admit I was unaware of MatchData's offset method. That's cool.
Using string.scan() should be only slightly slower than the
while/index() loop do to the inherent yield in scan {}.
If you are comming from Perl, I would also recommend to stick with
Regexp.last_match instead of $~ for clarity. I did 5+ years of Perl
but I'll be damned if I remember what all the $symbol vars stand for
without looking them up.
 
T

tony summerfelt

Logan Capaldo ha escrito:


That should work okay (well, it should be new_string << ..., thou).
I'll admit I was unaware of MatchData's offset method. That's cool.
Using string.scan() should be only slightly slower than the
while/index() loop do to the inherent yield in scan {}.
If you are comming from Perl, I would also recommend to stick with
Regexp.last_match instead of $~ for clarity. I did 5+ years of Perl
but I'll be damned if I remember what all the $symbol vars stand for
without looking them up.

http://home.cogeco.ca/~tsummerfelt1
ROVING SWARM: http://groups.yahoo.com/group/roving_swarm/
telnet://ventedspleen.dyndns.org
 
T

Thomas, Mark - BLS CTR

=20
tony said:
i noticed that all the ruby solutions presented were longer than the
original perl code. i found the perl code more readable... which is
unusual for most perl-ruby comparisons :)

Well, I wouldn't consider it unusual for the code to be longer when you
are trying to duplicate the functionality of a keyword of another
language that doesn't exist in Ruby!

Perhaps if String#scan made MatchData objects available as requested
here: http://www.rcrchive.net/rcr/show/276 the Ruby solution would be
cleaner.

- Mark.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,576
Members
45,054
Latest member
LucyCarper

Latest Threads

Top