(newbie Q) opposite of inspect for strings

Dear All

I am a novice in Ruby, and I appologize for asking such a basic
questions, but I did not found its answer in the Ruby in a Nutshell
book and after 10 minutes of Googling.

What is is opposite of inspect for strings, ie the function parsing
strings external representation (as strings)?

i.e. I do know that "a\tb".inspect gives the 6 character string
"\"a\\tb\"" but what is the method or function that, given the
argument "\"a\\tb\"" produces the "a\tb" string of 3 characters?

Also how can I easily parse (ie read) from a file such a string like
the output of inspect?

Again, apologies for asking probably a FAQ (which I didn't found in)

Regards.

···

--
Basile STARYNKEVITCH http://starynkevitch.net/Basile/
email: basile<at>starynkevitch<dot>net
aliases: basile<at>tunes<dot>org = bstarynk<at>nerim<dot>net
8, rue de la Faïencerie, 92340 Bourg La Reine, France

What is is opposite of inspect for strings, ie the function parsing
strings external representation (as strings)?

i.e. I do know that "a\tb".inspect gives the 6 character string
"\"a\\tb\"" but what is the method or function that, given the
argument "\"a\\tb\"" produces the "a\tb" string of 3 characters?

I'll try this, assuming I unserstand you correctly.

a="a\tb"

=> "a\tb"

p a.to_s

"a\tb"

Of course, calling to_s() on itself perhaps in this instance is silly,
as you know what it is, but I think that does what you're asking?

Also how can I easily parse (ie read) from a file such a string like
the output of inspect?

Can you provide an example of what you mean? Such as sample data?

-- Thomas Adam

···

--
"One of us is a cigar stand, and one of us is a lovely blue incandescent
guillotine" -- Stephen Malkmus, "Type Slowly" from "Brighten The Corners"

Dear All

I am a novice in Ruby, and I appologize for asking such a basic
questions, but I did not found its answer in the Ruby in a Nutshell
book and after 10 minutes of Googling.

What is is opposite of inspect for strings, ie the function parsing
strings external representation (as strings)?

i.e. I do know that "a\tb".inspect gives the 6 character string
"\"a\\tb\"" but what is the method or function that, given the
argument "\"a\\tb\"" produces the "a\tb" string of 3 characters?

Is this what you mean?

irb(main):001:0> str = "a\tb"
=> "a\tb"
irb(main):002:0> in_file = str.inspect
=> "\"a\\tb\""
irb(main):003:0> rebuilt = eval in_file
=> "a\tb"

Also how can I easily parse (ie read) from a file such a string like
the output of inspect?

Not sure I understand the question here. Do you know how to open a file and read from it or is that what you want to see?

James Edward Gray II

···

On May 18, 2005, at 3:45 PM, Basile Starynkevitch [news] wrote:

There used to be a library out there somewhere for doing this with
almost any object (using #inspect as a marshaling format). It does not
appear to be listed on the RAA, though. I wish I could remember the
name; perhaps someone else remembers it.

Paul

(citing me, Basile S.)

What is is opposite of inspect for strings, ie the function parsing
strings external representation (as strings)?

i.e. I do know that "a\tb".inspect gives the 6 character string
"\"a\\tb\"" but what is the method or function that, given the
argument "\"a\\tb\"" produces the "a\tb" string of 3 characters?

I'll try this, assuming I understand you correctly.

Sorry for having expressed myself poorly. I mean

  a="a\tb"

binds variable a to a 3 character string (a, tab, b)

  aa=a.inspect

binds variable aa to a 6 character string (dblquote, a, backslash, t,
b, dblquote)

I'm desperately seeking a function f such that

    b = f(aa)

binds variable b to a 3 character string which is equal to the value
of a, or I am seeking a method m such that

    c = aa.m

binds variable c to a 3 character string (a, tab, b) equal to the
value of a.

The to_s method is not a valuable substitute for m since aa.to_s is a
6 character string (equal to aa)

Also how can I easily parse (ie read) from a file such a string like
the output of inspect?

Actually I'm just trying to code in a quick and dirty way a ruby
script dumping into a textual form a (rather small) GDBM file, whoses
keys are all alphanumeric (and data are arbitrary binary strings). So
far, I've managed to code the following script which seems to work.

  #! /usr/bin/ruby
  # $Id: gdbmdump 1 2005-05-18 20:45:15Z basile $
  ## -*- ruby -*-

  require 'gdbm'

  srcdbmname=ARGV[0]
  destxtname=ARGV[1]

  STDERR.printf("start dumping gdbm %s into %s\n", srcdbmname, destxtname)

  if (not File.exists?(srcdbmname)) then
    STDERR.printf("source dbm %s does not exist\n", srcdbmname);
    exit(1)
  end

  keyarr=Array::new

  GDBM.open(srcdbmname, 0400) do |gdbm|
    nbk=0
    gdbm.each do |key,val|
      if /^[a-zA-Z0-9+*._@,!(){}-]*$/ =~ key then
        keyarr << key
        nbk = nbk + 1
      else
        STDERR.printf("bad key %s in file %s\n", key.inspect, srcdbmname);
        exit(1)
      end
    end
    STDERR.printf("got and sorting %d keys\n", nbk)
    keyarr.sort!
    if (File.exists?(destxtname)) then
      File.rename(destxtname,destxtname+"~")
    end
    File.open(destxtname, "w") do |out|
      keyarr.each do |key|
        val=gdbm[key]
        out.printf("%s\t%s\n", key, val.inspect)
      end
    end
  end

  STDERR.printf("end dumping gdbm %s into %s\n", srcdbmname, destxtname)

  ##eof $Id: gdbmdump 1 2005-05-18 20:45:15Z basile $

A typical output of the above script is

  ab "12"
  cd "45"

where the file starts at the column a, and where keys and data are
separated by a tabulation.

My goal was to code the corresponding loading script gdbmload; the
overall motivation for these 2 scripts is to manage under version
control (Subversion) a GDBM file (by dumping it to & reloading it from
a textual format, and by having a "canonical" dump format of it by
sorting the keys; I don"t want to version control the GDBM binary file
-because it is machine dependent- but a dump format of it, obtained
thru this gdbmdump script and the opposite gdbmload script to be
written)

I am really confused and ashamed of asking such basic questions. My
apologies to all, and a big thanks to Thomas Adam for having taken the
time to answer them.

Regards.

···

On 2005-05-18, Thomas Adam <thomas@edulinux.homeunix.org> wrote:
--
Basile STARYNKEVITCH Basile STARYNKEVITCH
email: basile<at>starynkevitch<dot>net
aliases: basile<at>tunes<dot>org = bstarynk<at>nerim<dot>net
8, rue de la Faïencerie, 92340 Bourg La Reine, France

Paul Brannan <pbrannan@atdesk.com> writes:

There used to be a library out there somewhere for doing this with
almost any object (using #inspect as a marshaling format). It does not
appear to be listed on the RAA, though. I wish I could remember the
name; perhaps someone else remembers it.

While I do not know it, I would be extremely interested in it.

Something like Lisp's READ is missing in Ruby.

···

Paul

--
Christian Neukirchen <chneukirchen@gmail.com> http://chneukirchen.org

Paul Brannan wrote:

There used to be a library out there somewhere for doing this with
almost any object (using #inspect as a marshaling format). It does not
appear to be listed on the RAA, though. I wish I could remember the
name; perhaps someone else remembers it.

Maybe you mean this?

http://raa.ruby-lang.org/project/amarshal/

[snip the script]

A typical output of the above script is

  ab "12"
  cd "45"

where the file starts at the column a, and where keys and data are
separated by a tabulation.

My goal was to code the corresponding loading script gdbmload; the
overall motivation for these 2 scripts is to manage under version
control (Subversion) a GDBM file (by dumping it to & reloading it from
a textual format, and by having a "canonical" dump format of it by
sorting the keys; I don"t want to version control the GDBM binary file
-because it is machine dependent- but a dump format of it, obtained
thru this gdbmdump script and the opposite gdbmload script to be
written)

Ah-ha!

You want YAML. It gives you a great plain-text representation that you can load/dump with ease and works great with revision control.

···

On 18 May 2005, at 14:25, Basile Starynkevitch [news] wrote:

--
Eric Hodel - drbrain@segment7.net - http://segment7.net
FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04

What you probably need is eval:

  irb(main):001:0> VERSION
  => "1.8.2"
  irb(main):002:0> a = "a\tb"
  => "a\tb"
  irb(main):003:0> aa = a.inspect
  => "\"a\\tb\""
  irb(main):004:0> b = eval(aa)
  => "a\tb"
  irb(main):005:0> a == b
  => true

Of course, you want to be careful when using eval, but it should cut
it for the simple case...

Jacob Fugal

···

On 5/18/05, Basile Starynkevitch [news] <basile-news@starynkevitch.net> wrote:

Sorry for having expressed myself poorly. I mean

  a="a\tb"

binds variable a to a 3 character string (a, tab, b)

  aa=a.inspect

binds variable aa to a 6 character string (dblquote, a, backslash, t,
b, dblquote)

I'm desperately seeking a function f such that

    b = f(aa)

binds variable b to a 3 character string which is equal to the value
of a, or I am seeking a method m such that

    c = aa.m

binds variable c to a 3 character string (a, tab, b) equal to the
value of a.

The to_s method is not a valuable substitute for m since aa.to_s is a
6 character string (equal to aa)

Thanks to all who replied. Yes, I was missing the cumfort of LISP READ
ability.

Any by the way, I coded in C the equivalent of what I wanted to code
in Ruby. Yo can download it here
http://starynkevitch.net/Basile/gdbmtext.c and it is a tiny utility
dumping & loading GDBM associative files into and from textual files.
I am quite surprise that Debian don"t seems to have such (or an
equivalent) utility (to dump & restore GDBM files into textual
formats)

Again, sorry for this offtopic post, and for my naive questions on
Ruby. If ruby developpers are reading me, they might consider adding
into some future version of Ruby the opposite function of inspect for
strings only (without going into the risks of eval, just parsing
strings...)

Regards.

···

On 2005-05-18, Basile Starynkevitch [news] <basile-news@starynkevitch.net> wrote:

Actually I'm just trying to code in a quick and dirty way a ruby
script dumping into a textual form a (rather small) GDBM file, whoses
keys are all alphanumeric (and data are arbitrary binary strings). So
far, I've managed to code the following script which seems to work.

--
Basile STARYNKEVITCH Basile STARYNKEVITCH
email: basile<at>starynkevitch<dot>net
aliases: basile<at>tunes<dot>org = bstarynk<at>nerim<dot>net
8, rue de la Faïencerie, 92340 Bourg La Reine, France

I'm desperately seeking a function f such that

    b = f(aa)

binds variable b to a 3 character string which is equal to the value
of a, or I am seeking a method m such that

    c = aa.m

binds variable c to a 3 character string (a, tab, b) equal to the
value of a.

The to_s method is not a valuable substitute for m since aa.to_s is a
6 character string (equal to aa)

What you probably need is eval:

A big thanks for this suggestion!

  irb(main):001:0> VERSION
=> "1.8.2"
  irb(main):002:0> a = "a\tb"
=> "a\tb"
  irb(main):003:0> aa = a.inspect
=> "\"a\\tb\""
  irb(main):004:0> b = eval(aa)
=> "a\tb"
  irb(main):005:0> a == b
=> true

Of course, you want to be careful when using eval, but it should cut
it for the simple case...

Is there some specialized version which does not evaluate its
(arbitrary) input, but just unformat a formatted string (and no more,
in particular refuse non-string lexemes such as arbitrary [dangerous]
ruby expressions)?

Regards.

···

On 2005-05-18, Jacob Fugal <lukfugl@gmail.com> wrote:

On 5/18/05, Basile Starynkevitch [news] <basile-news@starynkevitch.net> wrote:

--
Basile STARYNKEVITCH Basile STARYNKEVITCH
email: basile<at>starynkevitch<dot>net
aliases: basile<at>tunes<dot>org = bstarynk<at>nerim<dot>net
8, rue de la Faïencerie, 92340 Bourg La Reine, France

"Basile Starynkevitch [news]" <basile-news@starynkevitch.net> writes:

Actually I'm just trying to code in a quick and dirty way a ruby
script dumping into a textual form a (rather small) GDBM file, whoses
keys are all alphanumeric (and data are arbitrary binary strings). So
far, I've managed to code the following script which seems to work.

Thanks to all who replied. Yes, I was missing the cumfort of LISP READ
ability.

Any by the way, I coded in C the equivalent of what I wanted to code
in Ruby. Yo can download it here
http://starynkevitch.net/Basile/gdbmtext.c and it is a tiny utility
dumping & loading GDBM associative files into and from textual files.
I am quite surprise that Debian don"t seems to have such (or an
equivalent) utility (to dump & restore GDBM files into textual
formats)

I'm not sure about GDBM, but for Berkeley DB, there is dbdump IIRC.

···

On 2005-05-18, Basile Starynkevitch [news] <basile-news@starynkevitch.net> wrote:

Basile STARYNKEVITCH Basile STARYNKEVITCH

--
Christian Neukirchen <chneukirchen@gmail.com> http://chneukirchen.org

> What you probably need is eval:

A big thanks for this suggestion!

You're welcome :slight_smile:

> Of course, you want to be careful when using eval, but it should cut
> it for the simple case...

Is there some specialized version which does not evaluate its
(arbitrary) input, but just unformat a formatted string (and no more,
in particular refuse non-string lexemes such as arbitrary [dangerous]
ruby expressions)?

Unfortunately no. A possibility would be to write an encapsulating
method using a regex to verify the input:

  def unescapeString( str )
    raise TypeError, "Argument must be 'just a string'" unless
      str =~ /some nasty regex/
    eval( str )
  end

I don't really want to deal with writing that regex, though, so I'll
leave it as an exercise for the reader. :slight_smile:

Jacob Fugal

···

On 5/18/05, Basile Starynkevitch [news] <basile-news@starynkevitch.net> wrote:

On 2005-05-18, Jacob Fugal <lukfugl@gmail.com> wrote:

Jacob Fugal wrote:

Of course, you want to be careful when using eval, but it should cut
it for the simple case...

Is there some specialized version which does not evaluate its
(arbitrary) input, but just unformat a formatted string (and no more,
in particular refuse non-string lexemes such as arbitrary [dangerous]
ruby expressions)?

Unfortunately no. A possibility would be to write an encapsulating
method using a regex to verify the input:

  def unescapeString( str )
    raise TypeError, "Argument must be 'just a string'" unless
      str =~ /some nasty regex/
    eval( str )
  end

I don't really want to deal with writing that regex, though, so I'll
leave it as an exercise for the reader. :slight_smile:

Hm, what you have to check is if the string to be eval'd represents
_exactly_ one ruby string-literal. So, native regex could be
/^"[^"]*"$/

This will work as long as your string doesn't contain (escaped) doublequotes - e.g. '"'.inspect =~ /^"[^"]*"$/ fails.

The general rule is to ignore one character after a backslash, or
to ignore 1-3 digits after a backslash, if the first character after a backslash is a digit (from 0-7)

That leads to
/^"(([^"\\])|(\\[^0-7])|(\\[0-7][0-7]?[0-7]?))*"$/

It basically says: First a quite, then either something harmless (no quote or backslash), or a backslash any a abitrary char, or a backslash
and one to three digits, and at the one a quote. The middle part may
occur zeor or more times.

Using that, you can even omit the eval completly. Try this:

class String
  def uninspect
    return nil unless self =~ /^"(([^"\\])|(\\[^0-7])|(\\[0-7][0-7]?[0-7]?))*"$/
    (gsub(/\\([^0-7])/) { $1 }).gsub(/\\([0-7][0-7]?[0-7]?)/) { $1.to_i(8).chr }
  end
end

It implement the trhe rules above, and for every possible
string str == str.inspect.uninspect should hold...

greetings, Florian Pflug