Ruby loop order?

自古美人都是妖i 提交于 2020-01-05 05:39:25

问题


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 }rng

Iterates 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 succ method. A TypeError is raised if the object does not have succ method 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 (#each and methods inherited from Enumerable) expect the begin object to implement a succ method to return the next object in sequence.

So, while it isn't spelled out directly, it is clear that Range#each works by

  1. Repeatedly sending the succ message to the begin object (and then to the object that was returned by succ, and then to that object, and so forth), and
  2. 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:

succnew_str

Returns 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!