Anomoly using pattern to remove superfluous final \, if present

  • Thread starter Richard Lionheart
  • Start date
R

Richard Lionheart

Hi All,

The following Ruby script displays use of a pattern to remove a superfluous
backslash in a string if present. It works as intended with two "toy"
situations, but fails when applied to an environment string running under
Windows.

Can anyone tell me where I erred?

TIA,
Richard

============ Ruby pgm ===========

# Executed under Windows 2000

s1 = "ab\\\\"
puts "s1 before: \"#{s1}\" (two backslashes)"
s1.chop! if s1.reverse =~ /^\\\\/
puts "s1 after: \"#{s1}\" (redced to a single backslash)"

s2 = "ab\\"
puts "s2 before: \"#{s2}\" (single backslash)"
s2.chop! if s2.reverse =~ /^\\\\/
puts "s2 after: \"#{s2}\" (single backslash, undisturbed)"

s3 = ENV["UserProfile"]
puts "s3: \"#{s3}\""
sCookiesPath = s3 + "\\"
puts "Cookies path before: \"#{sCookiesPath}\" (single backslash)"
sCookiesPath.chop! if sCookiesPath.reverse !~ /^\\\\/
puts "Cookies path after: \"#{sCookiesPath}\" (single backslash removed -
why)"

<<'OUTPUT'
rubyw PatternsTest.rb
s1 before: "ab\\" (two backslashes)
s1 after: "ab\" (redced to a single backslash)
s2 before: "ab\" (single backslash)
s2 after: "ab\" (single backslash, undisturbed)
s3: "G:\Documents and Settings\RLMuller"
Cookies path before: "G:\Documents and Settings\RLMuller\" (single
backslash)
Cookies path after: "G:\Documents and Settings\RLMuller" (single backslash
removed - why)
Exit code: 0
OUTPUT
 
R

Robert Klemme

Richard Lionheart said:
Hi All,

The following Ruby script displays use of a pattern to remove a superfluous
backslash in a string if present. It works as intended with two "toy"
situations, but fails when applied to an environment string running under
Windows.

Can anyone tell me where I erred?

You rather want str.gsub!(/\\$/, '') than str.chop! if you want to remove
trailing backslashes.

See the documentation for chop!:
http://www.ruby-doc.org/docs/rdoc/1.9/classes/String.html#M001300

robert

TIA,
Richard

============ Ruby pgm ===========

# Executed under Windows 2000

s1 = "ab\\\\"
puts "s1 before: \"#{s1}\" (two backslashes)"
s1.chop! if s1.reverse =~ /^\\\\/
puts "s1 after: \"#{s1}\" (redced to a single backslash)"

s2 = "ab\\"
puts "s2 before: \"#{s2}\" (single backslash)"
s2.chop! if s2.reverse =~ /^\\\\/
puts "s2 after: \"#{s2}\" (single backslash, undisturbed)"

s3 = ENV["UserProfile"]
puts "s3: \"#{s3}\""
sCookiesPath = s3 + "\\"
puts "Cookies path before: \"#{sCookiesPath}\" (single backslash)"
sCookiesPath.chop! if sCookiesPath.reverse !~ /^\\\\/
puts "Cookies path after: \"#{sCookiesPath}\" (single backslash removed -
why)"

<<'OUTPUT'
rubyw PatternsTest.rb
s1 before: "ab\\" (two backslashes)
s1 after: "ab\" (redced to a single backslash)
s2 before: "ab\" (single backslash)
s2 after: "ab\" (single backslash, undisturbed)
s3: "G:\Documents and Settings\RLMuller"
Cookies path before: "G:\Documents and Settings\RLMuller\" (single
backslash)
Cookies path after: "G:\Documents and Settings\RLMuller" (single backslash
removed - why)
Exit code: 0
OUTPUT
 
D

daz

Richard said:
Hi All,

The following Ruby script displays use of a pattern to remove a superfluous
backslash in a string if present. It works as intended with two "toy"
situations, but fails when applied to an environment string running under
Windows.

Can anyone tell me where I erred?


s2.chop! if s2.reverse =~ /^\\\\/

sCookiesPath.chop! if sCookiesPath.reverse !~ /^\\\\/

You changed =~ to !=
The reversed path doesn't begin with double slash,
so you chop! the single slash.


["xyz\\", "xyz\\\\"].each do |s|
puts '----------', s
s.chop! if s.reverse =~ /^\\\\/
puts s
end


# Also:
# s.sub!(/\\\\\Z/, '\\')
# works for:
# s.chop! if s.reverse =~ /^\\\\/


daz
 
R

Robert Klemme

daz said:
Richard said:
Hi All,

The following Ruby script displays use of a pattern to remove a superfluous
backslash in a string if present. It works as intended with two "toy"
situations, but fails when applied to an environment string running under
Windows.

Can anyone tell me where I erred?


s2.chop! if s2.reverse =~ /^\\\\/

sCookiesPath.chop! if sCookiesPath.reverse !~ /^\\\\/

You changed =~ to !=
The reversed path doesn't begin with double slash,
so you chop! the single slash.


["xyz\\", "xyz\\\\"].each do |s|
puts '----------', s
s.chop! if s.reverse =~ /^\\\\/
puts s
end


# Also:
# s.sub!(/\\\\\Z/, '\\')
# works for:
# s.chop! if s.reverse =~ /^\\\\/

It seems to me quite inefficient to reverse a string only to match it with
"^".

s.chop! if /\\$/ =~ s

I guess another efficient method is

s.slice!(-1,1) if s[-1] == ?\\

Regards

robert
 
K

Kaspar Schiess

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Richard Lionheart wrote:
| Hi All,
|
| The following Ruby script displays use of a pattern to remove a
superfluous
| backslash in a string if present. It works as intended with two "toy"
| situations, but fails when applied to an environment string running under
| Windows.
|
| Can anyone tell me where I erred?
|
| TIA,
| Richard
|
| ============ Ruby pgm ===========
|
| # Executed under Windows 2000
|
| s1 = "ab\\\\"
| puts "s1 before: \"#{s1}\" (two backslashes)"
| s1.chop! if s1.reverse =~ /^\\\\/
| puts "s1 after: \"#{s1}\" (redced to a single backslash)"
|
| s2 = "ab\\"
| puts "s2 before: \"#{s2}\" (single backslash)"
| s2.chop! if s2.reverse =~ /^\\\\/
| puts "s2 after: \"#{s2}\" (single backslash, undisturbed)"
|
| s3 = ENV["UserProfile"]
| puts "s3: \"#{s3}\""
| sCookiesPath = s3 + "\\"
| puts "Cookies path before: \"#{sCookiesPath}\" (single backslash)"
| sCookiesPath.chop! if sCookiesPath.reverse !~ /^\\\\/
| puts "Cookies path after: \"#{sCookiesPath}\" (single backslash removed -
| why)"
|
| <<'OUTPUT'
|
|>rubyw PatternsTest.rb
|
| s1 before: "ab\\" (two backslashes)
| s1 after: "ab\" (redced to a single backslash)
| s2 before: "ab\" (single backslash)
| s2 after: "ab\" (single backslash, undisturbed)
| s3: "G:\Documents and Settings\RLMuller"
| Cookies path before: "G:\Documents and Settings\RLMuller\" (single
| backslash)
| Cookies path after: "G:\Documents and Settings\RLMuller" (single backslash
| removed - why)
|
|>Exit code: 0

Was that a trick question ? ;)

kaspar

semantics & semiotics
code manufacture

www.tua.ch/ruby
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.4 (MingW32)
Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org

iD8DBQFA7lucFifl4CA0ImQRAgiYAJ9jtzZpvwR2RkWukKIHpJvtom+NQgCgpqO9
HoUWXlqb6bC4Y5pCP6ondQI=
=FwF7
-----END PGP SIGNATURE-----
 
R

Richard Lionheart

Daz,

You have eyes like an eagle!! Thank you very much for showing me the error
my tired, old eyes couldn't see.

Regards,
Richard
 
R

Richard Lionheart

Hi Robert,

I originally sent this reply directly to you rather than the group. It's
repeated here in case the first one got lost in your "bit bucket" and to
mention an adaptation for the problem at hand
It seems to me quite inefficient to reverse a string
only to match it with "^".

s.chop! if /\\$/ =~ s

I guess another efficient method is

s.slice!(-1,1) if s[-1] == ?\\

Excellent guidance!! In this case, I'll employ the first since it involves
fewer keystrokes, though I expect the second might be a microsecond faster.

My goal was to chop a final backslash it was immediately preceded by another
backslash. So I'll use:

s.chop! if /\\\\$/ =~ s

Again, thanks for your insight!

Regards,
Richard
 
R

Richard Lionheart

Hi Kaspar,

Like my reply to Robert, I originally sent this reply directly to you rather
than the group. It's repeated here in case the first one got lost in your
"bit bucket." and to
mention an adaptation for the problem at hand :)
Was that a trick question ? ;)

No, it was my stupidity late at night. But it elicited a fast and succinct
correction from Daz and a more efficient (hence more correct, IMHO) approach
from Robert.

So aside from having my problem solved, I got a little more Ruby tutoring.
Not bad for a simple NG post, eh?

Best wishes,
Richard
 
R

Robert Klemme

Richard Lionheart said:
Hi Robert,

I originally sent this reply directly to you rather than the group. It's
repeated here in case the first one got lost in your "bit bucket" and to
mention an adaptation for the problem at hand
It seems to me quite inefficient to reverse a string
only to match it with "^".

s.chop! if /\\$/ =~ s

I guess another efficient method is

s.slice!(-1,1) if s[-1] == ?\\

Excellent guidance!! In this case, I'll employ the first since it involves
fewer keystrokes, though I expect the second might be a microsecond faster.

My goal was to chop a final backslash it was immediately preceded by another
backslash.

Ok, then my suggestion was not a solution to your problem.
So I'll use:

s.chop! if /\\\\$/ =~ s

Personally I would not use chop! since it is rather meant to remove record
separators (similar to chomp! but not as sophisticated, see here:
http://www.ruby-doc.org/docs/rdoc/1.9/classes/String.html#M001293

In your case I'd prefer

s.sub!( /\\\\\z/, '\\' )
Again, thanks for your insight!

You're welcome.

Kind regards

robert
 
R

Richard Lionheart

Hi Robert,
Ok, then my suggestion was not a solution to your problem.

Au contraire ... that's my feeble at French, a language I can't speak :)
I think your suggestion *was* essentially a solution to my problem. It
merely need the tweak I mentioned, as follows.
Personally I would not use chop! since it is rather meant to remove record
separators (similar to chomp! but not as sophisticated, see here:
http://www.ruby-doc.org/docs/rdoc/1.9/classes/String.html#M001293

As I read it (in the section entitled "str.chop => new_str"), the web page
your referenced indicates that chop is intended to remove *any* last
character; it merely has special semantics for record separators to
transcend the divergence of Windows from Unix.
In your case I'd prefer

s.sub!( /\\\\\z/, '\\' )

I assume "z" is a typo for "$" and I further assume that using pattern
matching is much less efficient than directly "chopping" (though the
difference is imperceptible for the amount of data usually processed by
scripting languages.)

I apologize for belaboring this point. Again, I'm in your debt for your
thoughtful responses.

Best wishes,
Richard
 
F

Florian Gross

Moin!

Richard said:
I assume "z" is a typo for "$" and I further assume that using pattern
matching is much less efficient than directly "chopping" (though the
difference is imperceptible for the amount of data usually processed by
scripting languages.)

\z is the very end of a String. It will always match after the last
character of a String.

$ is the end of a line. It will match before any \n character.

There's also \Z which is the end of a String. It will match if you are
at the end of the String or before a \n that is at the end of a String.

Regards,
Florian Gross
 
R

Robert

Richard said:
Hi Robert,



Au contraire ... that's my feeble at French, a language I can't speak :)
I think your suggestion *was* essentially a solution to my problem. It
merely need the tweak I mentioned, as follows.




As I read it (in the section entitled "str.chop => new_str"), the web page
your referenced indicates that chop is intended to remove *any* last
character; it merely has special semantics for record separators to
transcend the divergence of Windows from Unix.

Well, yes. Technically that's true. Maybe I made the fault to put it
into the same bag with chomp, which is what I usually use when reading
files.
I assume "z" is a typo for "$" and I further assume that using pattern
matching is much less efficient than directly "chopping" (though the
difference is imperceptible for the amount of data usually processed by
scripting languages.)

Well, if you really want to know it benchmark the two vs. each other and
see which one is faster. When it comes to performance, intuition is
often wrong. Measuring is the only way to get reliable results.
I apologize for belaboring this point. Again, I'm in your debt for your
thoughtful responses.

You're welcome

Kind regards

robert
 
R

Richard Lionheart

Hi Florian and Robert,

Again I squeezed out a little more education through NG posts! I heartily
thank both of you for the time and effort you took on my behalf and the
additional guidance you have generously provided me. I hope others have
benefited as much as I have from this thread.

Warmest regards,
Richard
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,743
Messages
2,569,478
Members
44,899
Latest member
RodneyMcAu

Latest Threads

Top