Ruby equiv of perl pos

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

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

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

$ 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

snacktime wrote:

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

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

···

On Aug 12, 2006, at 4:33 PM, snacktime wrote:

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

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 }
}

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.

gga wrote:

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

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

···

On Aug 13, 2006, at 3:40 PM, gga wrote:

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.

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.

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.

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.

http://home.cogeco.ca/~tsummerfelt1
ROVING SWARM: Yahoo | Mail, Weather, Search, Politics, News, Finance, Sports & Videos
telnet://ventedspleen.dyndns.org

···

On Mon, 14 Aug 2006 14:20:10 +0900, you wrote:

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.

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 :slight_smile:

http://home.cogeco.ca/~tsummerfelt1
ROVING SWARM: Yahoo | Mail, Weather, Search, Politics, News, Finance, Sports & Videos
telnet://ventedspleen.dyndns.org

···

On Mon, 14 Aug 2006 14:20:10 +0900, you wrote:

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

That should work okay

tony summerfelt wrote:

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 :slight_smile:

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: RCR 276: Make String#scan, #gsub, and #sub yield MatchData objects the Ruby solution would be
cleaner.

- Mark.