Backslash substitution

don’t know why… but this is not working
a=" xxxxxx\tttt\3.4.2\uuuu"
puts a.gsub(’\’,’/’)

And the result is:
xxxxxx ttt.4.2uuuu

what i want is xxxxxxx/tttt/3.4.2/uuuu

Subject: backslash substitution
Date: gio 21 feb 13 07:26:23 +0900

Quoting Mario R. ([email protected]):

don’t know why… but this is not working
a=" xxxxxx\tttt\3.4.2\uuuu"
puts a.gsub(’\’,’/’)

There has been a recent thread about this. You string should be
defined as.

a=" xxxxxx\tttt\3.4.2\uuuu"

Carlo

Yes I know… but i cannot change the string… the string it is like it
is… so i need to modify it later on and that’s the problme

Carlo E. Prelz wrote in post #1098178:

Subject: backslash substitution
Date: gio 21 feb 13 07:26:23 +0900

Subject: Re: backslash substitution
Date: gio 21 feb 13 07:33:50 +0900

Quoting Mario R. ([email protected]):

Yes I know… but i cannot change the string… the string it is like it
is… so i need to modify it later on and that’s the problme

?

If you substitute characters, you change the string.

Carlo

you mean by using gsub… in the expample i posted i tried but didn’t
work

Carlo E. Prelz wrote in post #1098182:

If you substitute characters, you change the string.

I cannot modify the string by myself… the string it is like it is…
is given as an argument so i cannot modify it by writing doubles

Subject: Re: backslash substitution
Date: gio 21 feb 13 07:48:43 +0900
Sorry for the delay!

Quoting Mario R. ([email protected]):

you mean by using gsub… in the expample i posted i tried but didn’t
work

irb(main):002:0> a=" xxxxxx\tttt\3.4.2\uuuu"
=> " xxxxxx\tttt\3.4.2\uuuu"
irb(main):003:0> puts a.gsub(’\’,’/’)
xxxxxx/tttt/3.4.2/uuuu
=> nil

What does not work?

PS:

irb(main):004:0> a="\a\b"
=> “\a\b”
irb(main):005:0> a.length
=> 4
irb(main):006:0> a.chars
=> ["\", “a”, “\”, “b”]
irb(main):007:0>

On 21.02.2013 10:57, Mario R. wrote:

I cannot modify the string by myself… the string it is like it
is…
is given as an argument so i cannot modify it by writing doubles

Carlo’s point is that your string as it stands does not contain any
backslashes. E.g.

a=" xxxxxx\tttt\3.4.2\uuuu"
=> " xxxxxx\tttt\003.4.2uuuu"

puts a
xxxxxx ttt.4.2uuuu
=> nil

So your attempt to substitute them is destined to fail.

I think doing this in irb might help illuminate the issue. Please read
the whole thing, and then read it again, and then if you think you
understand it, read it again and type along in your own ruby/irb.

irb(main):001:0> a=" xxxxxx\tttt\3.4.2"
=> " xxxxxx\tttt\x03.4.2"

I now have a string, called a. It has some characters in. You may
notice that in my 1.9.2 Ruby the “\3” becomes “\x03” when inspected.
Interesting. (I suspect that in 1.8 it would have become “\03”, but I
can’t remember that far back to be certain.)

irb(main):002:0> a.unpack(‘C*’)
=> [32, 120, 120, 120, 120, 120, 120, 9, 116, 116, 116, 3, 46, 52, 46,
50]

All I’m doing here is extracting the integer values of each ASCII
character in my a string. Did you note that there are 16
bytes/characters, even though I typed 18 characters between the quotes
in my original statement? Note also that the eighth byte, corresponding
with my first backslash, has the value 9. I happen to know that 9 is
actually the ASCII TAB character, which is usually referred to as “\t”.
I hope some bells are ringing here.

Odd, let me convert those integer byte values into strings, one by one,
so we can see them in a different way.

irb(main):003:0> a.unpack(‘C*’).map{|int| int.chr }
=> [" ", “x”, “x”, “x”, “x”, “x”, “x”, “\t”, “t”, “t”, “t”, “\x03”,
“.”, “4”, “.”, “2”]

Each string contains a single character. Notice how Ruby has
represented 9 as “\t” and 3 as “\x03”, which look to be more than one
character each? That representation goes both ways (i.e. you may
require multiple characters of source code to represent a single
character of actual data.)

Now let’s have a look at the gsub bit:

irb(main):004:0> ‘\’
=> “\”
irb(main):005:0> ‘\’.unpack(‘C*’)
=> [92]
irb(main):006:0> ‘\’.unpack(‘C*’).map{|int| int.chr }
=> ["\"]

You can see quite plainly that ruby interprets the ‘\’ as a single
byte, with value 92, that is the ASCII backslash character.

Looking at the earlier code, there are no 92-bytes in the original
string. I must infer, then, that gsub is quite correctly replacing 100%
of those 92-characters with a forward slash. (In case you missed it,
100% of 0 is 0.)

Here is a little further experimentation on my part:

irb(main):006:0> b=" xxxxxx\tttt\3.4.2"
=> " xxxxxx\tttt\3.4.2"
irb(main):007:0> b.unpack(‘C*’)
=> [32, 120, 120, 120, 120, 120, 120, 92, 116, 116, 116, 116, 92, 51,
46, 52, 46, 50]

Ahh, now b contains 18 characters, which is what we thought should
have been in a. To achieve this, I had to actually type 20
characters between the double-quotes (doubling up the backslashes.)

See how the eighth byte is now 92? And so…

irb(main):008:0> b.gsub(’\’, ‘/’)
=> " xxxxxx/tttt/3.4.2"

Aha!

Therefore, since a is apparently “like it is” and can’t be changed, I
would first be asking: what is it actually like? Does it contain
backslash characters, or does it contain TAB characters? You can find
this out fairly easily by adding the equivalent of:

STDERR.puts a.unpack(‘C*’).inspect

…immediately before your current gsub. Then, if there are 92s in the
array, your gsub should be working, and our debugging effort should move
elsewhere.

However, if there are 9s in the array, then you have some serious
issues, because it means that someone who meant to put 92s into their
string actually put 9s and 3s and whatever other rubbish in there. It’s
rather tricky (or impossible) to get them back out.

Let me leave you with a simple illustration:

irb(main):009:0> a=“bbb\aaa\7.6.5”
=> “bbb\aaa\a.6.5”
irb(main):010:0> a.unpack(‘C*’)
=> [98, 98, 98, 7, 97, 97, 7, 46, 54, 46, 53]

Oh noes! When I type “\a” and “\7” Ruby interprets them both as the
same thing! I have no way to “fix up” those integer 7s to either “\a”
or “\7” because by the time it looks like a 7, I have no way of knowing
which it was originally meant to be.

If you’re in this situation, you need to go smack whoever messed up the
string in the first place. IMO

On Thu, Feb 21, 2013 at 5:32 AM, Matthew K. [email protected]
wrote:

can’t remember that far back to be certain.)
actually the ASCII TAB character, which is usually referred to as “\t”.
represented 9 as “\t” and 3 as “\x03”, which look to be more than one
irb(main):005:0> ‘\’.unpack(‘C*’)
100% of 0 is 0.)

=> [98, 98, 98, 7, 97, 97, 7, 46, 54, 46, 53]
Posted via http://www.ruby-forum.com/.

Try your experiment again, only instead of wrapping the string with
backslashes in double quotes, wrap it in single quotes. If the string
coming in is unchangeable, experimenting using double quotes initially
is incorrect, as that will interpolate.

irb(main):011:0> a = “xxxxxx\tttt\3.4.2\uuuu”
SyntaxError: (irb):11: invalid Unicode escape
a = “xxxxxx\tttt\3.4.2\uuuu”
^
from /home/tamara/.rvm/rubies/ruby-1.9.3-head/bin/irb:16:in `’
irb(main):012:0> a = ‘xxxxxx\tttt\3.4.2\uuuu’
“xxxxxx\tttt\3.4.2\uuuu”
irb(main):013:0> a.gsub(’\’,’/’)
“xxxxxx/tttt/3.4.2/uuuu”

The problem is I cannot put single or doubles since the value is given
as an argument in command line so the value is taken something like
this:

ARGV.each do |x|
  if !x["folder="].nil? then a=x.gsub("folder=","") end
end

Am 21.02.2013 11:26, schrieb Mario R.:

don’t know why… but this is not working
a=" xxxxxx\tttt\3.4.2\uuuu"
puts a.gsub(’\’,’/’)

And the result is:
xxxxxx ttt.4.2uuuu

what i want is xxxxxxx/tttt/3.4.2/uuuu

Your example string does not contain any backslashes!

Instead it contains for example a tab:

[1] pry(main)> puts “a\tb”
a b

You need to define the string using single quotes:

[2] pry(main)> puts ‘a\tb’
a\tb

Backslashes are interpreted differently in String literals
with single and double quotes.

Subject: Re: backslash substitution
Date: ven 22 feb 13 05:47:17 +0900

Quoting Mario R. ([email protected]):

The problem is I cannot put single or doubles since the value is given
as an argument in command line so the value is taken something like
this:

ARGV.each do |x|
  if !x["folder="].nil? then a=x.gsub("folder=","") end
end

You still did not get it…

A backslash is used to quote the following character so it transforms
it into a non-printable character. For example:

“\t” is a tab (ONE character, ascii 9)
“\b” is a backspace (ONE character, ascii 8)
“\a” is a bell character (ONE character, ascii 7)
“\e” is an escape (ONE character, ascii 27)

AND

“\” is a backslash (ONE character, ascii 92)

I don’t know what else to write…

Carlo

I found this solution… but i thought that Ruby had a better way:

x=“xxxxx P jjjjjj\0\1\2\3.4.1\4\5\6\7\8\9”
m=""
x.each_byte {|a|
if a<32 then
m+="/" + a.to_s()
else
m+=a.chr
end
}
puts m

Mario R. wrote in post #1098396:

The problem is I cannot put single or doubles since the value is given
as an argument in command line so the value is taken something like
this:

ARGV.each do |x|
  if !x["folder="].nil? then a=x.gsub("folder=","") end
end

Aha! Now some of what you’ve said starts to make sense.

I just created this file:

#test.rb:
a=nil
ARGV.each do |x|
if !x[“folder=”].nil? then a=x.gsub(“folder=”,"") end
end
p a

When I run it in Windows, I get this:

ruby test.rb
nil
ruby test.rb folder=a\b\c
“a\b\c”

So you can see that the Windows command prompt has interpreted the
single backslashes as backslashes, and passed them through to Ruby
faithfully.

If I run it in Linux I get this:

$ ruby test.rb
nil
$ ruby test.rb folder=a\b\c
“abc”
$ ruby test.rb folder=a\b\c
“a\b\c”

So you can see that bash (the command prompt I use) has interpreted the
backslashes as special characters, not entirely unlike the way ruby
would. However bash (and most *nix shells) give you options like this:

$ ruby test.rb folder=“a\b\c”
“a\b\c”
$ ruby test.rb folder=‘a\b\c’
“a\b\c”

The gsub line in Ruby would work just fine, but you also have to tell
your command prompt what you mean when you write a backslash.

Yep I have it… if anyone knows a simpler way… post it :wink:
Thanks for your help

On 22.02.2013 09:27, Mario R. wrote:

m+=a.chr

end
}
puts m

Has that really done what you want though?

puts m
xxxxx P jjjjjj/0/1/2/3.4.1/4/5/6/789

Mario R. wrote in post #1098399:

I found this solution… but i thought that Ruby had a better way:

x=“xxxxx P jjjjjj\0\1\2\3.4.1\4\5\6\7\8\9”
m=""
x.each_byte {|a|
if a<32 then
m+="/" + a.to_s()
else
m+=a.chr
end
}
puts m

If you persist on pushing down this path, indeed Ruby does have a better
way. Several. Legion. For example, and off the top of my head:

x.gsub(/[\x00-\x1F]/){|c|"\#{c.ord}"}

However, and I’ll say this one last time, your test code is FAULTY. It
doesn’t reflect the case you’re trying to test. Have a look really
closely at the “\8\9” part, have a look how that’s interpreted by Ruby.
Use the code snippets I so caringly wrote and demonstrated earlier.

And then, try reverse-engineering this string using your method:

x=“c:\a\b\e\xface”

If you want to test your gsub line and make sure it’s replacing
slashes with other slashes, either try it by putting it inside
the actual ARGV.each block, or give it some input that matches what ARGV
actually contains.

If your ARGV contains rubbish, fix it at the calling context.

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs