Forum: Ruby Cutting a piece of text

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
8694182da7e6d41d3e362e3c1ee65a4e?d=identicon&s=25 Zdebel (Guest)
on 2006-02-12 17:17
Helo !
I've started to learn ruby and I'm amazed with it. Now I have a problem
that I can't solve. If I have a string like this:
"<lyrics artist=XXX album=XXX title=XXX> Lalalalala </lyrics>" how can I
cut the " artist=XXX album=XXX title=XXX" part, so it would look like:
"<lyrcis> Lalalalala </lyrics>" Could you please help me ?
4299e35bacef054df40583da2d51edea?d=identicon&s=25 James Gray (bbazzarrakk)
on 2006-02-12 17:58
(Received via mailing list)
On Feb 12, 2006, at 10:18 AM, Zdebel wrote:

> Helo !
> I've started to learn ruby and I'm amazed with it. Now I have a
> problem
> that I can't solve. If I have a string like this:
> "<lyrics artist=XXX album=XXX title=XXX> Lalalalala </lyrics>" how
> can I
> cut the " artist=XXX album=XXX title=XXX" part, so it would look like:
> "<lyrcis> Lalalalala </lyrics>" Could you please help me ?

You can do it with a regular expression like the following, but I
must stress that this isn't very robust:

 >> "<lyrics artist=XXX album=XXX title=XXX> Lalalalala </lyrics>".sub
(/<(\w+)[^>]+>/, "<\\1>")
=> "<lyrics> Lalalalala </lyrics>"

Hope that helps.

James Edward Gray II
8694182da7e6d41d3e362e3c1ee65a4e?d=identicon&s=25 Zdebel (Guest)
on 2006-02-12 18:05
James Gray wrote:
> On Feb 12, 2006, at 10:18 AM, Zdebel wrote:
>
>> Helo !
>> I've started to learn ruby and I'm amazed with it. Now I have a
>> problem
>> that I can't solve. If I have a string like this:
>> "<lyrics artist=XXX album=XXX title=XXX> Lalalalala </lyrics>" how
>> can I
>> cut the " artist=XXX album=XXX title=XXX" part, so it would look like:
>> "<lyrcis> Lalalalala </lyrics>" Could you please help me ?
>
> You can do it with a regular expression like the following, but I
> must stress that this isn't very robust:
>
>  >> "<lyrics artist=XXX album=XXX title=XXX> Lalalalala </lyrics>".sub
> (/<(\w+)[^>]+>/, "<\\1>")
> => "<lyrics> Lalalalala </lyrics>"
>
> Hope that helps.
>
> James Edward Gray II

:O, wow it works, I wish I knew how this (/<(\w+)[^>]+>/, "<\\1>")
regular expresion works :). Anyway thank you, you helped me very much.
430ea1cba106cc65b7687d66e9df4f06?d=identicon&s=25 David Vallner (Guest)
on 2006-02-12 18:05
(Received via mailing list)
DÅ?a Nedeľa 12 Február 2006 17:18 Zdebel napísal:
> Helo !
> I've started to learn ruby and I'm amazed with it. Now I have a problem
> that I can't solve. If I have a string like this:
> "<lyrics artist=XXX album=XXX title=XXX> Lalalalala </lyrics>" how can I
> cut the " artist=XXX album=XXX title=XXX" part, so it would look like:
> "<lyrcis> Lalalalala </lyrics>" Could you please help me ?

The very geeky, and most probably least error-prone way would be
whacking the
string with a DOM parser, clearing the attributes, and then printing it
out
again. Unfortunately, I haven't been doing any DOM manipulation in Ruby,
so I
can't provide code.

David Vallner
4299e35bacef054df40583da2d51edea?d=identicon&s=25 James Gray (bbazzarrakk)
on 2006-02-12 18:14
(Received via mailing list)
On Feb 12, 2006, at 11:05 AM, David Vallner wrote:

>
> The very geeky, and most probably least error-prone way would be
> whacking the
> string with a DOM parser, clearing the attributes, and then
> printing it out
> again. Unfortunately, I haven't been doing any DOM manipulation in
> Ruby, so I
> can't provide code.

The following is how you do it for valid XML, but the posted example
wasn't quite:

#!/usr/local/bin/ruby -w

require "rexml/document"

doc = "<lyrics artist='XXX' album='XXX' title='XXX'> Lalalalala </
lyrics>"
xml = REXML::Document.new(doc)
xml.root.attributes.clear
xml.write
puts

__END__

James Edward Gray II
Feaa8237a324cc32cc52c3cc3c92e781?d=identicon&s=25 unknown (Guest)
on 2006-02-12 18:18
(Received via mailing list)
Learn regular expressions. Here's a not great example:

a =  "<lyrics artist=XXX album=XXX title=XXX> Lalalalala </lyrics>"
b = a.gsub(/\w*=\w*/  , "")
c = b.gsub(/\s/, "")
print  c, "\n"

<lyrics>Lalalalala</lyrics>


A slightly (yes very slightly) more realistic  example:

a =  '<lyrics artist="Prince" album="purplerain" title="computerblue">
Lalalalala </lyrics>'
b = a.gsub(/\w*="\w*"/  , "")
c = b.gsub(/\s/, "")
print  c, "\n"


<lyrics>Lalalalala</lyrics>


And what if there are spaces in a tag:

a =  '<lyrics artist="Prince" album="purplerain" title="Computer Blue">
Lalalalala </lyrics>'
b = a.gsub(/\w*=".*"/  , "")
c = b.gsub(/\s/, "")
4299e35bacef054df40583da2d51edea?d=identicon&s=25 James Gray (bbazzarrakk)
on 2006-02-12 18:20
(Received via mailing list)
On Feb 12, 2006, at 11:05 AM, Zdebel wrote:

> I wish I knew how this (/<(\w+)[^>]+>/, "<\\1>")
> regular expresion works :).

It reads:

/ <      # find a < character
   (      # capture this next part into $1 (\\1 in the replacement
string)
     \w+  # followed by one or more word characters
   )      # end capture
   [^>]+  # followed by one or more non > characters
   >      # and finally a > character
/x


The replacement just restores the <\w+> and leaves out the [^>]+ part
(the space and attributes).

Hope that helps.

James Edward Gray II
8694182da7e6d41d3e362e3c1ee65a4e?d=identicon&s=25 Zdebel (Guest)
on 2006-02-12 18:33
Big thank you too all of you guys for such a response. This helped me
alot and my script is working, but I will practice more using your
advices :)
B97225f66bb5caac601b12735d430a0d?d=identicon&s=25 Marcin MielżyÅ?ski (Guest)
on 2006-02-12 19:08
(Received via mailing list)
James Edward Gray II wrote:

>  >> "<lyrics artist=XXX album=XXX title=XXX> Lalalalala
> </lyrics>".sub(/<(\w+)[^>]+>/, "<\\1>")
> => "<lyrics> Lalalalala </lyrics>"

reluctant would a bit faster:

p "<lyrics artist=XXX album=XXX title=XXX> Lalalalala
</lyrics>".gsub(/<(\w+).*?>/, "<\\1>")


lopex
4299e35bacef054df40583da2d51edea?d=identicon&s=25 James Gray (bbazzarrakk)
on 2006-02-12 19:30
(Received via mailing list)
On Feb 12, 2006, at 12:08 PM, Marcin MielżyÅ?ski wrote:

> James Edward Gray II wrote:
>
>>  >> "<lyrics artist=XXX album=XXX title=XXX> Lalalalala </
>> lyrics>".sub(/<(\w+)[^>]+>/, "<\\1>")
>> => "<lyrics> Lalalalala </lyrics>"
>
> reluctant would a bit faster:
>
> p "<lyrics artist=XXX album=XXX title=XXX> Lalalalala </
> lyrics>".gsub(/<(\w+).*?>/, "<\\1>")

Are you sure?

$ ruby regexp_time.rb
Rehearsal -------------------------------------------------
/<(w+)[^>]+>/   7.210000   0.030000   7.240000 (  7.266166)
/<(w+).*?>/     7.710000   0.020000   7.730000 (  7.757304)
--------------------------------------- total: 14.970000sec

                     user     system      total        real
/<(w+)[^>]+>/   7.170000   0.030000   7.200000 (  7.227075)
/<(w+).*?>/     7.730000   0.020000   7.750000 (  7.777196)
$ cat regexp_time.rb
#!/usr/local/bin/ruby -w

require "benchmark"

tests = 1000000
data  = "<lyrics artist=XXX album=XXX title=XXX> Lalalalala </lyrics>"

Benchmark.bmbm do |x|
   x.report("/<(\w+)[^>]+>/") do
     tests.times { data.sub(/<(\w+)[^>]+>/, "<\\1>") }
   end
   x.report("/<(\w+).*?>/") do
     tests.times { data.sub(/<(\w+).*?>/, "<\\1>") }
   end
end

__END__

;)

James Edward Gray II
430ea1cba106cc65b7687d66e9df4f06?d=identicon&s=25 David Vallner (Guest)
on 2006-02-12 21:21
(Received via mailing list)
DÅ?a Nedeľa 12 Február 2006 19:30 James Edward Gray II napísal:
> > lyrics>".gsub(/<(\w+).*?>/, "<\\1>")
> /<(w+)[^>]+>/   7.170000   0.030000   7.200000 (  7.227075)
>    x.report("/<(\w+)[^>]+>/") do
>
> James Edward Gray II

The nongreedy match has to "back up" and retry on every character after
the
tag name, whileas James' [^>] doesn't ever have to back up. In fact,
even a
greedy .* would probably be faster than a nongreedy one in this case.

Gotta love the black art that is optimizing regexps.

David Vallner
B97225f66bb5caac601b12735d430a0d?d=identicon&s=25 Marcin MielżyÅ?ski (Guest)
on 2006-02-12 21:38
(Received via mailing list)
David Vallner wrote:

> The nongreedy match has to "back up" and retry on every character after the
> tag name, whileas James' [^>] doesn't ever have to back up. In fact, even a
> greedy .* would probably be faster than a nongreedy one in this case.
>
> Gotta love the black art that is optimizing regexps.
>

Ooops.. You are right!

But as I read greedy quantifiers do backtrack as well (but not in the
case above).

/a+aa/ =~ "aaaaa"
will backtrack two characters

only possesive quantifier (in oniguruma e.g.) consumes in the real,
greedy way.

so
/a++aa/ =~ "aaaaa"
won't match.

lopex
430ea1cba106cc65b7687d66e9df4f06?d=identicon&s=25 David Vallner (Guest)
on 2006-02-12 22:35
(Received via mailing list)
DÅ?a Nedeľa 12 Február 2006 21:38 Marcin MielżyÅ?ski napísal:
> But as I read greedy quantifiers do backtrack as well (but not in the
> won't match.
>
> lopex

Yes, they do backtrack. The point is in using the one that you expect to
backtrack less.

Since in this case we very well knew there's going to be quite a few
characters after the first word, the nongreedy quantifier was slower.

Where the REAL black magic is whether a greedy or possessive
quantification of
the [^>] variant would be faster. *snicker* Anyone running 1.9 able to
BM
this?

David Vallner
2ee1a7960cc761a6e92efb5000c0f2c9?d=identicon&s=25 William James (Guest)
on 2006-02-13 08:58
(Received via mailing list)
Zdebel wrote:
> Helo !
> I've started to learn ruby and I'm amazed with it. Now I have a problem
> that I can't solve. If I have a string like this:
> "<lyrics artist=XXX album=XXX title=XXX> Lalalalala </lyrics>" how can I
> cut the " artist=XXX album=XXX title=XXX" part, so it would look like:
> "<lyrcis> Lalalalala </lyrics>" Could you please help me ?
>
> --
> Posted via http://www.ruby-forum.com/.

p " <lyrics artist=XXX album=XXX title=XXX> Lalalalala </lyrics>".
sub(/\s+[^<>]*(?=>)/, '' )

p " <lyrics artist=XXX album=XXX title=XXX> Lalalalala </lyrics>".
scan( /\G ( [^<]+ ) | \G ( < \S* ) [^>]* ( > ) /x ).
flatten.compact.join
This topic is locked and can not be replied to.