Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I'm trying to write \1 in a string, but I can't do it. I would appreciate if somebody helped me with this strange behaviour. Here is an example with some explaining.
EDIT: Adding example output
puts "\1 <- null"
puts "\\1 <- slash one"
works!
but typing
"\1"
"\\1"
in the irb command line yields
"\1"
=> "\u0001
"\\1"
=> "\\1"
There are a few ways to get it:
"\\1"
'\1'
?\\ + ?1
Remember that the way it will show up is always "\\1", which means literal backslash, one, which is what you want. The way to know that this is correct is to use puts:
puts "\\1"
# => \1
Inside of double-quoted strings, backslashes have significant meaning. \n means the newline character. In single quoted strings, that's two characters: backslash and n.
You can even test this:
"\\1".chars
# => ["\\", "1"]
'\1'.chars
# => ["\\", "1"]
So you can see Ruby is interpreting that as two characters, not three. Don't be fooled by the second backslash inside a double-quoted string. That's how a literal backslash is represented.
Have you tried puts '\1'? (single quotes instead of double)
I'm not 100% sure what you're asking but if that helps, cheers.
Your command line shows "\1" because irb does .inspect on the object, which escapes the string. So essentially \1 is properly stored, but when it's displaying it, it adds another \ to indicate to you that it's escaped
When I'm in IRB and type \1, the value returned is \u0001 which is Ruby's way of
representing the character.
When I write puts('\1), the behavior is the same in IRB and when running
a script. I see a unicode character map as follows
0 0
0 1
This won't be the same output on all platforms (it depends on how unicode is
displayed). So that's probably why you see no output on the repl.it example.
Related
I have the following string, \'e4, which I can't seem to get printed to my IRB console.
My attempts:
"\'e4" gives me back "'e4"
"\\'e4" gives me back "\\'e4"
Any ideas?
Double-quoted strings will always show up with double backslashes in irb due to the way they're escaped.
If you want to see what it actually is:
puts "\\'e4"
# => \'e4
Your first attempt is read as "literal quote e 4" and the second is "literal backslash quote e 4". The second one is correct regardless of how it's displayed.
my Question is how I can convert the STDIN of cmd ARGV or gets from hex to ascii
I know that if I assigned hex string to variable it'll be converted once I print it
ex
hex_var = "\x41\41\x41\41"
puts hex_var
The result will be
AAAA
but I need to get the value from command line by (ARGV or gets)
say I've this lines
s = ARGV
puts s
# another idea
puts s[0].gsub('x' , '\x')
then I ran
ruby gett.rb \x41\x41\x41\x41
I got
\x41\x41\x41\x41
is there a way to get it work ?
There are a couple problems you're dealing with here. The first you've already tried to address, but I don't think your solution is really ideal. The backslashes you're passing in with the command line argument are being evaluated by the shell, and are never making it to the ruby script. If you're going to simply do a gsub in the script, there's no reason to even pass them in. And doing it your way means any 'x' in the arguments will get swapped out, even those that aren't being used to indicate a hex. It would be better to double escape the \ in the argument if possible. Without context of where the values are coming from, it's hard to say with way would actually be better.
ruby gett.rb \\x41\\x41
That way ARGV will actually get '\x41\x41', which is closer to what you want.
It's still not exactly what you want, though, because ARGV arguments are created without expression substitution (as though they are in single quotes). So Ruby is escaping that \ even though you don't want it to. Essentially you need to take that and re-evaluate it as though it were in double quotes.
eval('"%s"' % s)
where s is the string.
So to put it all together, you could end up with either of these:
# ruby gett.rb \x41\x41
ARGV.each do |s|
s = s.gsub('x' , '\x')
p eval('"%s"' % s)
end
# => "AA"
# ruby gett.rb \\x41\\x41
ARGV.each do |s|
p eval('"%s"' % s)
end
# => "AA"
Backlashes entered in the console will be interpreted by the shell and will
not make it into your Ruby script, unless you enter two backlashes in a row,
in which case you script will get a literal backlash and no automatic
conversion of hexadecimal character codes following those backlashes.
You can convert these escaped codes to characters manually if you replace the last line of your script with this:
puts s.gsub(/\\x([[:xdigit:]]{1,2})/) { $1.hex.chr }
Then run it with double backlashed input:
$ ruby gett.rb \\x41\\x42\\x43
ABC
When fetching user input through gets or similar, only a single backslash will be need to be entered by the user for each character escape, since that will indeed be passed to your script as literal backslashes and thus handled correctly by the above gsub call.
An alternative way when parsing command line arguments would be to let the shell interpret the character escapes for you. How to do this will depend on what shell you are using. If using bash, it can be done
like this:
$ echo $'\x41\x42\x43'
ABC
$ ruby -e 'puts ARGV' $'\x41\x42\x43'
ABC
I entered this access token value
864876322670016\u00257C4e1d481ecad9eb45b9386745.1-1026038548\u00257CshuA8v7lgo7-hRr2AjbUBd3shek
on a form but it was returned with double backslash like this
864876322670016\\u00257C4e1d481ecad9eb45b9386745.1-1026038548\\u00257CshuA8v7lgo7-hRr2AjbUBd3shek
I'm passing this value to Facebook GraphAPI and this returns an error.
How can I get return replace the double backslash with a single one? or is there a way for the double backslash to not appear?
Are you sure it's actually returned with double backslashes? Internally strings with backslashes will look like they have double backslashes because Ruby is escaping them:
> a = 'aaa\bbb\ccc'
=> "aaa\\bbb\\ccc" # Looks like doubles
> a
=> "aaa\\bbb\\ccc"
> a.inspect
=> "\"aaa\\\\bbb\\\\ccc\"" # Looks even worse
> puts a
aaa\bbb\ccc # ...but it isn't
But if they are double backslashes you can do something like this:
> puts aa
aaa\\bbb\\ccc # String with double backslash
> aa.gsub!("\\\\", "\\")
> puts aa
aaa\bbb\ccc
It's just the way it's being displayed, in escaped form. Your error is likely elsewhere.
This is a common misinterpretation of the output, and a little confusing when you first see it, as Casper has pointed out.
From this question/answer, where the person's issue was essentially the same:
Dang it. I forgot that when the result is displayed in double quotes it shows it escaped.
There's also a short discussion of this perceived issue in this blog post.
Hey I'm trying to use a regex to count the number of quotes in a string that are not preceded by a backslash..
for example the following string:
"\"Some text
"\"Some \"text
The code I have was previously using String#count('"')
obviously this is not good enough
When I count the quotes on both these examples I need the result only to be 1
I have been searching here for similar questions and ive tried using lookbehinds but cannot get them to work in ruby.
I have tried the following regexs on Rubular from this previous question
/[^\\]"/
^"((?<!\\)[^"]+)"
^"([^"]|(?<!\)\\")"
None of them give me the results im after
Maybe a regex is not the way to do that. Maybe a programatic approach is the solution
How about string.count('"') - string.count("\\"")?
result = subject.scan(
/(?: # match either
^ # start-of-string\/line
| # or
\G # the position where the previous match ended
| # or
[^\\] # one non-backslash character
) # then
(\\\\)* # match an even number of backslashes (0 is even, too)
" # match a quote/x)
gives you an array of all quote characters (possibly with a preceding non-quote character) except unescaped ones.
The \G anchor is needed to match successive quotes, and the (\\\\)* makes sure that backslashes are only counted as escaping characters if they occur in odd numbers before the quote (to take Amarghosh's correct caveat into account).
I'm trying to learn RegEx in Ruby, based on what I'm reading in "The Rails Way". But, even this simple example has me stumped. I can't tell if it is a typo or not:
text.gsub(/\s/, "-").gsub([^\W-], '').downcase
It seems to me that this would replace all spaces with -, then anywhere a string starts with a non letter or number followed by a dash, replace that with ''. But, using irb, it fails first on ^:
syntax error, unexpected '^', expecting ']'
If I take out the ^, it fails again on the W.
>> text = "I love spaces"
=> "I love spaces"
>> text.gsub(/\s/, "-").gsub(/[^\W-]/, '').downcase
=> "--"
Missing //
Although this makes a little more sense :-)
>> text.gsub(/\s/, "-").gsub(/([^\W-])/, '\1').downcase
=> "i-love-spaces"
And this is probably what is meant
>> text.gsub(/\s/, "-").gsub(/[^\w-]/, '').downcase
=> "i-love-spaces"
\W means "not a word"
\w means "a word"
The // generate a regexp object
/[^\W-]/.class
=> Regexp
Step 1: Add this to your bookmarks. Whenever I need to look up regexes, it's my first stop
Step 2: Let's walk through your code
text.gsub(/\s/, "-")
You're calling the gsub function, and giving it 2 parameters.
The first parameter is /\s/, which is ruby for "create a new regexp containing \s (the // are like special "" for regexes).
The second parameter is the string "-".
This will therefore replace all whitespace characters with hyphens. So far, so good.
.gsub([^\W-], '').downcase
Next you call gsub again, passing it 2 parameters.
The first parameter is [^\W-]. Because we didn't quote it in forward-slashes, ruby will literally try run that code. [] creates an array, then it tries to put ^\W- into the array, which is not valid code, so it breaks.
Changing it to /[^\W-]/ gives us a valid regex.
Looking at the regex, the [] says 'match any character in this group. The group contains \W (which means non-word character) and -, so the regex should match any non-word character, or any hyphen.
As the second thing you pass to gsub is an empty string, it should end up replacing all the non-word characters and hyphens with empty string (thereby stripping them out )
.downcase
Which just converts the string to lower case.
Hope this helps :-)
You forgot the slashes. It should be /[^\W-]/
Well, .gsub(/[^\W-]/,'') says replace anything that's a not word nor a - for nothing.
You probably want
>> text.gsub(/\s/, "-").gsub(/[^\w-]/, '').downcase
=> "i-love-spaces"
Lower case \w (\W is just the opposite)
The slashes are to say that the thing between them is a regular expression, much like quotes say the thing between them is a string.