Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to validate that a string is a proper hexadecimal value in Ruby?

Tags:

regex

ruby

hex

I am writing a 6502 assembler in Ruby. I am looking for a way to validate hexadecimal operands in string form. I understand that the String object provides a "hex" method to return a number, but here's a problem I run into:

  "0A".hex #=> 10 - a valid hexadecimal value
  "0Z".hex #=>  0 - invalid, produces a zero
"asfd".hex #=> 10 - Why 10?  I guess it reads 'a' first and stops at 's'?

You will get some odd results by typing in a bunch of gibberish. What I need is a way to first verify that the value is a legit hex string.

I was playing around with regular expressions, and realized I can do this:

true if "0A" =~ /[A-Fa-f0-9]/
#=> true

true if "0Z" =~ /[A-Fa-f0-9]/
#=> true <-- PROBLEM

I'm not sure how to address this issue. I need to be able to verify that letters are only A-F and that if it is just numbers that is ok too.

I'm hoping to avoid spaghetti code, riddled with "if" statements. I am hoping that someone could provide a "one-liner" or some form of elegent code.

Thanks!

like image 350
JohnnyStarr Avatar asked Dec 05 '13 15:12

JohnnyStarr


3 Answers

!str[/\H/] will look for invalid hex values.

like image 160
hirolau Avatar answered Nov 01 '22 15:11

hirolau


String#hex does not interpret the whole string as hex, it extracts from the beginning of the string up to as far as it can be interpreted as hex. With "0Z", the "0" is valid hex, so it interpreted that part. With "asfd", the "a" is valid hex, so it interpreted that part.

like image 38
sawa Avatar answered Nov 01 '22 15:11

sawa


One method:

str.to_i(16).to_s(16) == str.downcase

Another:

str =~ /\A[a-f0-9]+\Z/i   # or simply /\A\h+\Z/ (see hirolau's answer)

About your regex, you have to use anchors (\A for begin of string and \Z for end of string) to say that you want the full string to match. Also, the + repeats the match for one or more characters.

Note that you could use ^ (begin of line) and $ (end of line), but this would allow strings like "something\n0A" to pass.

like image 29
Guilherme Bernal Avatar answered Nov 01 '22 17:11

Guilherme Bernal