[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

newbie Q) opposite of inspect for strings

Basile STARYNKEVITCH

5/18/2005 8:41:00 PM


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.n...
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
13 Answers

Thomas Adam

5/18/2005 8:50:00 PM

0

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


James Gray

5/18/2005 9:19:00 PM

0

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

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



Basile STARYNKEVITCH

5/18/2005 9:22:00 PM

0

On 2005-05-18, Thomas Adam <thomas@edulinux.homeunix.org> wrote:

(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.
--
Basile STARYNKEVITCH http://starynkevitch.n...
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

Eric Hodel

5/18/2005 9:43:00 PM

0

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

[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.

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



Jacob Fugal

5/18/2005 9:48:00 PM

0

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)

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


Basile STARYNKEVITCH

5/18/2005 9:53:00 PM

0

On 2005-05-18, Jacob Fugal <lukfugl@gmail.com> wrote:
> On 5/18/05, Basile Starynkevitch [news] <basile-news@starynkevitch.net> wrote:
>>
>> 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.


--
Basile STARYNKEVITCH http://starynkevitch.n...
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

Jacob Fugal

5/18/2005 10:02:00 PM

0

On 5/18/05, Basile Starynkevitch [news] <basile-news@starynkevitch.net> wrote:
> On 2005-05-18, Jacob Fugal <lukfugl@gmail.com> wrote:
> > What you probably need is eval:
>
> A big thanks for this suggestion!

You're welcome :)

> > 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. :)

Jacob Fugal


Paul Brannan

5/19/2005 2:25:00 PM

0

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




Christian Neukirchen

5/19/2005 3:31:00 PM

0

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://chneuk...


Florian Pflug

5/19/2005 8:58:00 PM

0

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. :)

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