问题
I'm trying to bruteforce a password. As I was playing with some loops, I've noticed there's a specific order. Like, if I have for i in '.'..'~' it puts
.
/
0
1
2
3
4
5
6
7
8
9
:
;
<
=
>
?
@
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
W
X
Y
Z
[
\
]
^
_
`
a
b
c
d
e
f
g
h
i
j
k
l
m
n
o
p
q
r
s
t
u
v
w
x
y
z
{
|
}
~
After seeing this, I wondered to myself "what is the loop order in Ruby?" What character is the highest priority and which is the lowest priority? Sorry if this question is basic. I just haven't found a site where anyone knows. If you have questions about the question just ask. I hope this is clear enough!
回答1:
The order is defined by the binary representation of the letters. Which, in turn, is defined by a standard. The standard used is ASCII (American Standard Code for Information Interchange).
http://www.asciitable.com/
Other encoding standards exist, like EBCDIC which is used by IBM mid-range computers.
回答2:
for / in is (mostly) syntactic sugar for each, so
for i in '.'..'~' do puts i end
is (roughly) equivalent (modulo local variable scope) to
('.'..'~').each do |i| puts i end
Which means that we have to look at Range#each for our answer (bold emphasis mine):
each {| i | block }→rngIterates over the elements of range, passing each in turn to the block.
The each method can only be used if the begin object of the range supports the
succmethod. ATypeErroris raised if the object does not havesuccmethod defined (like Float).
And the documentation for the Range class itself provides more details:
Custom Objects in Ranges
Ranges can be constructed using any objects that can be compared using the
<=>operator. Methods that treat the range as a sequence (#eachand methods inherited from Enumerable) expect the begin object to implement asuccmethod to return the next object in sequence.
So, while it isn't spelled out directly, it is clear that Range#each works by
- Repeatedly sending the
succmessage to the begin object (and then to the object that was returned bysucc, and then to that object, and so forth), and - Comparing the current element to the end object using the
<=>spaceship combined comparison operator to figure out whether to produce another object or end the loop.
Which means that we have to look at String#succ next:
succ→new_strReturns the successor to str. The successor is calculated by incrementing characters starting from the rightmost alphanumeric (or the rightmost character if there are no alphanumerics) in the string. Incrementing a digit always results in another digit, and incrementing a letter results in another letter of the same case. Incrementing nonalphanumerics uses the underlying character set’s collating sequence.
Basically, what this means is:
- incrementing a letter does what you expect
- incrementing a digit does what you expect
- incrementing something that is neither a letter nor a digit is arbitrary and dependent on the string's character set's collating sequence
In this particular case, you didn't tell us what the collating sequence of your string is, but I assume it is ASCII, which means you get what is colloquially called ASCIIbetical ordering.
回答3:
It's not about priority, but the order of their values. As already said, the characters have their own ASCII representation (E.g., 'a' value is 97 and 'z' value is 122).
You could see this for yourself trying this:
('a'..'z').each do |c|
puts c.ord
end
Analogously, this should also work:
(97..122).each do |i|
puts i.chr
end
来源:https://stackoverflow.com/questions/39458550/ruby-loop-order