Strings and member-operators

Hi:

I’m looking for a way to strip the quotes (and whitespace) off of a
string. Right now, I’m using:

class String
def stripQuotes
s = sub( ‘^"’, " " )
s.sub!( ‘"$’, " " )
return s.strip!
end
end

This hardly strikes me as the most elegant way. In particular, a nil is
returned if the string is unquoted, and the only way I can see to get
around this is by adding more regular expressions to check for the
existence of quotes.

A problem I’m having is that I can’t seem to figure out how to get at
the underlying string data (like an array) in a member function.

On a related note, and regardless of any suggestions on how to do what I
want to do, how does one call a member operator in a member function?

Thanks,
Cameron

Hi –

Hi:

I’m looking for a way to strip the quotes (and whitespace) off of a
string. Right now, I’m using:

class String
def stripQuotes
s = sub( ‘^"’, " " )
s.sub!( ‘"$’, " " )
return s.strip!
end
end

This hardly strikes me as the most elegant way. In particular, a nil is
returned if the string is unquoted, and the only way I can see to get
around this is by adding more regular expressions to check for the
existence of quotes.

A problem I’m having is that I can’t seem to figure out how to get at
the underlying string data (like an array) in a member function.

Here are a couple of possible ways to do this (untested for speed (and
multi-line-ness (so please modify as needed)))

irb(main):035:0> s
" "hi i am a string" "
irb(main):036:0> s.strip.sub(/^“(.*)”$/,‘\1’)
“hi i am a string”
irb(main):037:0> s.strip.delete(‘"’)
“hi i am a string”

The second one is only a good idea if you know that the only "
characters will be the ones you want to get rid of.

David

···

On Tue, 23 Jul 2002, the Bare wrote:


David Alan Black
home: dblack@candle.superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav

[snip - I think David addressed this?]

A problem I’m having is that I can’t seem to figure out how to get at
the underlying string data (like an array) in a member function.

Is it self you want? Within a method, that gives you access to the object
that the nethod belongs to.

class String
def printme
puts self
end
end

“abc”.printme # prints abc

On a related note, and regardless of any suggestions on how to do what I
want to do, how does one call a member operator in a member function?

Not sure I understand this… if an object understands an operator
(most/many
of which are really methods) then you should be able to call it from within
a method just fine.

Hal Fulton

···

----- Original Message -----
From: “the Bare” grrr@wild.net
Newsgroups: comp.lang.ruby
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Monday, July 22, 2002 6:05 PM
Subject: Strings and member-operators

class String

removes single or double quotes from around string

def unquote
astr = self.dup.strip
if astr[1…1] == ‘"’
return astr.reverse.chomp(‘"’).reverse.chomp(‘"’)
elsif astr[1…1] == “'”
return astr.reverse.chomp(“'”).reverse.chomp(“'”)
end
end

Inplace unquote

def unquote!
self.replace(unquote)
end

end

as you can see i added this to the String class so its available all the
time. but now that i think about it, it would probably be better to use:

return astr[1…-2]

don’t you think?

~transami

···

On Mon, 2002-07-22 at 17:05, the Bare wrote:

I’m looking for a way to strip the quotes (and whitespace) off of a
string.

For fun, lets see if we can do this test-first:

Lets write the first test:

class StripQuotesTest < Test::Unit::TestCase
  def test_do_nothing
    assert_equal("foo", "foo".stripQuotes)
  end
end

It fails. No surprise. Lets write some code:

class String
  def stripQuotes
    self
  end
end

Okay. The test passes. Not very interesting: by the name of
the test, the test really doesn’t do anything. So, lets write
another test:

class StripQuotesTest < Test::Unit::TestCase
  def test_do_nothing
    assert_equal("foo", "foo".stripQuotes)
  end

  def test_strip_doublequotes
    assert_equal("foo", "\"foo\"".stripQuotes,
      "didn't remove outer double quotes")
    assert_equal("\"foo", "\"foo".stripQuotes,
      "incorrectly removed leading unmatched quote")
    assert_equal("foo\"", "foo\"".stripQuotes,
      "incorrectly removed trailing unmatched quote")
    assert_equal("f\"oo", "f\"oo".stripQuotes,
      "incorrectly removed inner double quote")
  end
end

Of course, the test fails because it didn’t remove the outer quotes.
Lets write some code:

class String
  def stripQuotes
    unless (self =~ /^"(.*)"$/).nil?
      $1
    else
      self
    end
  end
end

Cool. Tests pass again. Now, lets handle the stripping of
whitespace with another test:

class StripQuotesTest < Test::Unit::TestCase
# previous cases omitted for brevity

  def test_strip_whitespace
    assert_equal("foo", "foo ".stripQuotes,
      "didn't strip trailing whitespace")
    assert_equal("foo", " foo".stripQuotes,
      "didn't strip leading whitespace")
    assert_equal("foo", " foo ".stripQuotes,
      "didn't strip leading and trailing whitespace")
    assert_equal("foo", "\" foo \"".stripQuotes,
      "didn't strip leading and trailing whitespace inside double quotes")
    assert_equal("\"foo\"", " \"foo\" ".stripQuotes,
      "incorrectly stripped double quotes")
  end
end

No surprise, the test doesn’t pass. Write some more code:

class String
  def stripQuotes
    unless (self =~ /^"(.*)"$/).nil?
      $1.strip
    else
      self.strip
    end
  end
end

The tests pass again, but the code’s getting smelly. There’s
some visible duplication. Lets refactor:

class String
  def stripQuotes
    self =~ /^"(.*)"$/
    ($1 || self).strip
  end
end

There, eliminated the duplication. It still doesn’t feel
right – now, we’re not explicitly checking the success of the
regexp match … luckily we have unit tests to let us know if
we make a mistake, though.

I’m sure someone’ll come up with an even more clever way of
doing this, but at least I had fun doing it. :wink:

– Dossy

···

On 2002.07.23, the Bare grrr@wild.net wrote:

I’m looking for a way to strip the quotes (and whitespace) off of a
string. Right now, I’m using:

class String
def stripQuotes
s = sub( ‘^"’, " " )
s.sub!( ‘"$’, " " )
return s.strip!
end
end

This hardly strikes me as the most elegant way. In particular, a nil is
returned if the string is unquoted, and the only way I can see to get
around this is by adding more regular expressions to check for the
existence of quotes.

A problem I’m having is that I can’t seem to figure out how to get at
the underlying string data (like an array) in a member function.

On a related note, and regardless of any suggestions on how to do what I
want to do, how does one call a member operator in a member function?


Dossy Shiobara mail: dossy@panoptic.com
Panoptic Computer Network web: http://www.panoptic.com/
“He realized the fastest way to change is to laugh at your own
folly – then you can let go and quickly move on.” (p. 70)

Hi –

To atone for the fact that my earlier suggestions didn’t do what the
original post asked for (as pointed out by Dossy on irc), I have
written a version that passes Dossy’s tests.

class String
  def stripQuotes
    self =~ /^"(.*)"$/
    ($1 || self).strip
  end
end

Here’s my version:

class String
def stripQuotes
/^("?)(.*?)(\1)$/.match(self)[2].strip
end
end

and one contribution to the test suite:

def test_empty_string
assert_equal(“”, “”.stripQuotes)
end

David

···

On Tue, 23 Jul 2002, Dossy wrote:


David Alan Black
home: dblack@candle.superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav

Hal E. Fulton wrote:

Is it self you want? Within a method, that gives you access to the object
that the nethod belongs to.

‘self’ is exactly what I wanted, as were all (or any) of the solutions
to my problem.

Thanks to everyone,
Cameron

Very cool. I wonder why you had to wrap \1 in parens, though.
Just for visual symmetry, or did it only work that way?

– Dossy

···

On 2002.07.23, David Alan Black dblack@candle.superlink.net wrote:

class String
def stripQuotes
/^("?)(.*?)(\1)$/.match(self)[2].strip
end
end


Dossy Shiobara mail: dossy@panoptic.com
Panoptic Computer Network web: http://www.panoptic.com/
“He realized the fastest way to change is to laugh at your own
folly – then you can let go and quickly move on.” (p. 70)

Hi –

···

On Tue, 23 Jul 2002, Dossy wrote:

On 2002.07.23, David Alan Black dblack@candle.superlink.net wrote:

class String
def stripQuotes
/^("?)(.*?)(\1)$/.match(self)[2].strip
end
end

Very cool. I wonder why you had to wrap \1 in parens, though.
Just for visual symmetry, or did it only work that way?

Good question. I think it was left over from some intermediate
version that used the grouping for something. It can definitely go.

David


David Alan Black
home: dblack@candle.superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav

Hello,

David Alan Black wrote:

Hi –

class String
def stripQuotes
/^("?)(.*?)(\1)$/.match(self)[2].strip
end
end

Very cool. I wonder why you had to wrap \1 in parens, though.
Just for visual symmetry, or did it only work that way?

Good question. I think it was left over from some intermediate
version that used the grouping for something. It can definitely go.

David

Is there an advantage to using .? there instead of .? (That second ‘?’
there is punctuation, not part of the regex). Or would there be no
difference at all, assuming there were no newlines in the matched string?
Speaking of which, isn’t it an idea to turn on the mutliline flag? Or use
\A…\z? You could butcher something like:

“Some quote”
— Some guy.

(I’m not very good with quotes ;))

···

On Tue, 23 Jul 2002, Dossy wrote:

On 2002.07.23, David Alan Black dblack@candle.superlink.net wrote:

Hi –

David Alan Black wrote:

Hi –

class String
def stripQuotes
/^("?)(.*?)(\1)$/.match(self)[2].strip
end
end

Is there an advantage to using .? there instead of .? (That second ‘?’
there is punctuation, not part of the regex). Or would there be no
difference at all, assuming there were no newlines in the matched string?
Speaking of which, isn’t it an idea to turn on the mutliline flag? Or use
\A…\z? You could butcher something like:

“Some quote”
— Some guy.

Hmmmm… Like the other thing Dossy pointed out (putting () around
\1), I think the ? was left over from some intermediate version where
it mattered.

OK, so now we’re looking at:

/^("?)(.*)\1$/.match(self)[2].strip

I hadn’t addressed the whole multi-line issue – it wasn’t in Dossy’s
test suite :slight_smile:

David

···

On Wed, 24 Jul 2002, George Ogata wrote:

On Tue, 23 Jul 2002, Dossy wrote:

On 2002.07.23, David Alan Black dblack@candle.superlink.net wrote:


David Alan Black
home: dblack@candle.superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav

let me get this straight? is the original question how to strip a string
and remove quotes?

/^("?)(.*)\1$/.match(self)[2].strip

this only does double quotes and its striping after the quotes removal.
is that what’s wanted? well, i’ll assume so. what about without regexp?

return str[1…-1].strip if str[0…0] + str[-1…-1] == ‘“”’

hmmm… you’d think there’d be a real simple way to do this without
regexp, can it get any simpler?

~transami

···

On Tue, 2002-07-23 at 09:38, David Alan Black wrote:

Hi –

On Wed, 24 Jul 2002, George Ogata wrote:

David Alan Black wrote:

Hi –

On Tue, 23 Jul 2002, Dossy wrote:

On 2002.07.23, David Alan Black dblack@candle.superlink.net wrote:

class String
def stripQuotes
/^("?)(.*?)(\1)$/.match(self)[2].strip
end
end

Is there an advantage to using .? there instead of .? (That second ‘?’
there is punctuation, not part of the regex). Or would there be no
difference at all, assuming there were no newlines in the matched string?
Speaking of which, isn’t it an idea to turn on the mutliline flag? Or use
\A…\z? You could butcher something like:

“Some quote”
— Some guy.

Hmmmm… Like the other thing Dossy pointed out (putting () around
\1), I think the ? was left over from some intermediate version where
it mattered.

OK, so now we’re looking at:

/^("?)(.*)\1$/.match(self)[2].strip

I hadn’t addressed the whole multi-line issue – it wasn’t in Dossy’s
test suite :slight_smile:

David


David Alan Black
home: dblack@candle.superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav


~transami

It’s faster using regexp. Fewer intermediate temporary objects created.

– Dossy

···

On 2002.07.24, Tom Sawyer transami@transami.net wrote:

let me get this straight? is the original question how to strip a string
and remove quotes?

/^("?)(.*)\1$/.match(self)[2].strip

this only does double quotes and its striping after the quotes removal.
is that what’s wanted? well, i’ll assume so. what about without regexp?

return str[1…-1].strip if str[0…0] + str[-1…-1] == ‘“”’

hmmm… you’d think there’d be a real simple way to do this without
regexp, can it get any simpler?


Dossy Shiobara mail: dossy@panoptic.com
Panoptic Computer Network web: http://www.panoptic.com/
“He realized the fastest way to change is to laugh at your own
folly – then you can let go and quickly move on.” (p. 70)

Hi –

let me get this straight? is the original question how to strip a string
and remove quotes?

/^("?)(.*)\1$/.match(self)[2].strip

this only does double quotes and its striping after the quotes removal.
is that what’s wanted? well, i’ll assume so. what about without regexp?

return str[1…-1].strip if str[0…0] + str[-1…-1] == ‘“”’

hmmm… you’d think there’d be a real simple way to do this without
regexp, can it get any simpler?

Well, I find the regex version simpler :slight_smile: To take care of single
quotes, by the way, just change it to:

/^(["']?)(.*)\1$/

But still, if you wanted to do it without using a regex, you could do
something like your code but you’d need an ‘else’ in there somewhere:

class String
def stripQuotes
if self[0] == ?" && self[-1] == self[0]
self[1…-2].strip
else
strip
end
end
end

(I’ve formatted it to be runnable with Dossy’s test suite.)

My thinking in doing this:

if self[0] == ?" && self[-1] == self[0]

was to make modifying it easier:

if %q{’ "}.include?(self[0]) …

(which is probably stupid, since it’s not like I’m really
parameterizing it), and also to avoid the ‘+’ operation because that
runs into problems with an empty string. In fact I think it would
also give weird results with the string ‘"’ (namely, it would see that
[0] and [-1] added up to ‘“”’, which is a false positive if you’re
looking for matching double quotes).

David

···

On Wed, 24 Jul 2002, Tom Sawyer wrote:


David Alan Black
home: dblack@candle.superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav

Oh, and your code doesn’t work, either. It doesn’t make all the
tests pass:

Loaded suite tc_ts_strip_quotes
Started...
..
Failure occurred in test_do_nothing(StripQuotesTest)
[tc_ts_strip_quotes.rb:5]: Expected <foo> but was <nil>
.
Failure occurred in test_strip_doublequotes(StripQuotesTest)
[tc_ts_strip_quotes.rb:9]: didn't remove outer double quotes. Expected
<foo> but was <foo">
.
Failure occurred in test_strip_whitespace(StripQuotesTest)
[tc_ts_strip_quotes.rb:20]: didn't strip trailing whitespace. Expected
<foo> but was <nil>

Finished in 0.00509 seconds.
3 runs, 3 assertions, 3 failures, 0 errors

– Dossy

···

On 2002.07.24, Dossy dossy@panoptic.com wrote:

On 2002.07.24, Tom Sawyer transami@transami.net wrote:

let me get this straight? is the original question how to strip a string
and remove quotes?

/^("?)(.*)\1$/.match(self)[2].strip

this only does double quotes and its striping after the quotes removal.
is that what’s wanted? well, i’ll assume so. what about without regexp?

return str[1…-1].strip if str[0…0] + str[-1…-1] == ‘“”’

hmmm… you’d think there’d be a real simple way to do this without
regexp, can it get any simpler?

It’s faster using regexp. Fewer intermediate temporary objects created.


Dossy Shiobara mail: dossy@panoptic.com
Panoptic Computer Network web: http://www.panoptic.com/
“He realized the fastest way to change is to laugh at your own
folly – then you can let go and quickly move on.” (p. 70)

(namely, it would see that

[0] and [-1] added up to ‘“”’, which is a false positive if you’re
looking for matching double quotes).

true but it would still return the right result. (my fix at least)

well, guess it goes to show. regexp are damn powerful, even if they
can’t solve every parsing problem, and are rather cryptic.

yet this thread has made me desire a new String method. one that can
pick out and join only particular characters:

"thanks".pick(0, -1)  # => "ts"

~transami

···

On Tue, 2002-07-23 at 10:54, David Alan Black wrote:

Hi –

On Wed, 24 Jul 2002, Tom Sawyer wrote:

let me get this straight? is the original question how to strip a string
and remove quotes?

/^("?)(.*)\1$/.match(self)[2].strip

this only does double quotes and its striping after the quotes removal.
is that what’s wanted? well, i’ll assume so. what about without regexp?

return str[1…-1].strip if str[0…0] + str[-1…-1] == ‘“”’

hmmm… you’d think there’d be a real simple way to do this without
regexp, can it get any simpler?

Well, I find the regex version simpler :slight_smile: To take care of single
quotes, by the way, just change it to:

/^(["']?)(.*)\1$/

But still, if you wanted to do it without using a regex, you could do
something like your code but you’d need an ‘else’ in there somewhere:

class String
def stripQuotes
if self[0] == ?" && self[-1] == self[0]
self[1…-2].strip
else
strip
end
end
end

(I’ve formatted it to be runnable with Dossy’s test suite.)

My thinking in doing this:

if self[0] == ?" && self[-1] == self[0]

was to make modifying it easier:

if %q{’ "}.include?(self[0]) …

(which is probably stupid, since it’s not like I’m really
parameterizing it), and also to avoid the ‘+’ operation because that
runs into problems with an empty string. In fact I think it would
also give weird results with the string ‘"’ (namely, it would see that
[0] and [-1] added up to ‘“”’, which is a false positive if you’re
looking for matching double quotes).

David


David Alan Black
home: dblack@candle.superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav


~transami

really? what did it fail on?

···

On Tue, 2002-07-23 at 10:24, Dossy wrote:

On 2002.07.24, Dossy dossy@panoptic.com wrote:

On 2002.07.24, Tom Sawyer transami@transami.net wrote:

let me get this straight? is the original question how to strip a string
and remove quotes?

/^("?)(.*)\1$/.match(self)[2].strip

this only does double quotes and its striping after the quotes removal.
is that what’s wanted? well, i’ll assume so. what about without regexp?

return str[1…-1].strip if str[0…0] + str[-1…-1] == ‘“”’

hmmm… you’d think there’d be a real simple way to do this without
regexp, can it get any simpler?

It’s faster using regexp. Fewer intermediate temporary objects created.

Oh, and your code doesn’t work, either. It doesn’t make all the
tests pass:

Loaded suite tc_ts_strip_quotes
Started...
..
Failure occurred in test_do_nothing(StripQuotesTest)
[tc_ts_strip_quotes.rb:5]: Expected <foo> but was <nil>
.
Failure occurred in test_strip_doublequotes(StripQuotesTest)
[tc_ts_strip_quotes.rb:9]: didn't remove outer double quotes. Expected
<foo> but was <foo">
.
Failure occurred in test_strip_whitespace(StripQuotesTest)
[tc_ts_strip_quotes.rb:20]: didn't strip trailing whitespace. Expected
<foo> but was <nil>

Finished in 0.00509 seconds.
3 runs, 3 assertions, 3 failures, 0 errors

– Dossy


Dossy Shiobara mail: dossy@panoptic.com
Panoptic Computer Network web: http://www.panoptic.com/
“He realized the fastest way to change is to laugh at your own
folly – then you can let go and quickly move on.” (p. 70)


~transami

Tom Sawyer transami@transami.net writes:

really? what did it fail on?

Dossy showed the output of the test suite:

Failure occurred in test_do_nothing(StripQuotesTest)
[tc_ts_strip_quotes.rb:5]: Expected <foo> but was <nil>
Failure occurred in test_strip_doublequotes(StripQuotesTest)
[tc_ts_strip_quotes.rb:9]: didn't remove outer double quotes. Expected
<foo> but was <foo">
Failure occurred in test_strip_whitespace(StripQuotesTest)
[tc_ts_strip_quotes.rb:20]: didn't strip trailing whitespace. Expected
<foo> but was <nil>
Finished in 0.00509 seconds.
3 runs, 3 assertions, 3 failures, 0 errors

ttyl,

···


Josh Huber

uh, not without the test suite…but i still had the old message so i
went back and looked at the test suite code and figured it out. jeez.
two simple bloopers a -1 was supposed to be a -2 and i wan’t returning
str on a non-match. does this pass now?

return str[0…0] + str[-1…-1] == ‘“”’ ? str[1…-2].strip : str

i was just trying to do it without regexp.

thanks,
transami

···

~

On Tue, 2002-07-23 at 10:42, Josh Huber wrote:

Tom Sawyer transami@transami.net writes:

really? what did it fail on?

Dossy showed the output of the test suite:

Failure occurred in test_do_nothing(StripQuotesTest)
[tc_ts_strip_quotes.rb:5]: Expected <foo> but was <nil>
Failure occurred in test_strip_doublequotes(StripQuotesTest)
[tc_ts_strip_quotes.rb:9]: didn't remove outer double quotes. Expected
<foo> but was <foo">
Failure occurred in test_strip_whitespace(StripQuotesTest)
[tc_ts_strip_quotes.rb:20]: didn't strip trailing whitespace. Expected
<foo> but was <nil>
Finished in 0.00509 seconds.
3 runs, 3 assertions, 3 failures, 0 errors

ttyl,


Josh Huber


~transami

It still doesn’t make the tests pass:

Loaded suite tc_ts_strip_quotes
Started...
....
Failure occurred in test_strip_whitespace(StripQuotesTest)
[tc_ts_strip_quotes.rb:20]: didn't strip trailing whitespace. Expected
<foo> but was <foo >

Finished in 0.003761 seconds.
3 runs, 6 assertions, 1 failures, 0 errors

Here’s the failed test case, to save you some time:

def test_strip_whitespace
  assert_equal("foo", "foo ".stripQuotes,
    "didn't strip trailing whitespace")
  assert_equal("foo", " foo".stripQuotes,
    "didn't strip leading whitespace")
  assert_equal("foo", " foo ".stripQuotes,
    "didn't strip leading and trailing whitespace")
  assert_equal("foo", "\" foo \"".stripQuotes,
    "didn't strip leading and trailing whitespace inside double quotes")
  assert_equal("\"foo\"", " \"foo\" ".stripQuotes,
    "incorrectly stripped double quotes")
end

Specifically, it was this one:

  assert_equal("foo", "foo ".stripQuotes,
    "didn't strip trailing whitespace")

– Dossy

···

On 2002.07.24, Tom Sawyer transami@transami.net wrote:

uh, not without the test suite…but i still had the old message so i
went back and looked at the test suite code and figured it out. jeez.
two simple bloopers a -1 was supposed to be a -2 and i wan’t returning
str on a non-match. does this pass now?

return str[0…0] + str[-1…-1] == ‘“”’ ? str[1…-2].strip : str

i was just trying to do it without regexp.


Dossy Shiobara mail: dossy@panoptic.com
Panoptic Computer Network web: http://www.panoptic.com/
“He realized the fastest way to change is to laugh at your own
folly – then you can let go and quickly move on.” (p. 70)