在我们重复做一些事情的时候,就需要使用循环了。而 AHK 正是能将复杂的手动工作自动化的工具,循环自然必不可少。但 AHK 中的循环也是多种多样的,我们慢慢道来。
一、简单循环
最简单的情况,我们知道要循环多少次,比如想连续按下 10 次回车键:
Loop, 10
{
Send, {Enter}
}
这样就可以了。在 Loop 后加上要循环的次数,然后大括号里边就是要循环执行的语句。当然我们可以先把循环的次数放进一个变量,这样更灵活些:
count := 10
Loop, %count%
{
Send, {Enter}
}
可以在循环体中使用 A_Index 来获取当前循环的次数。
或者有可能我们想一直循环执行:
Loop
{
Send, {Enter}
Sleep, 1000
}
这个就是死循环了,如果脚本不退出就会一直执行,某些情况我们确实需要这样。但更多情况,我们需要在满足某个条件时结束循环:
; 这个 stop 变量会在代码的其他地方修改,比如在某个定时器里
stop := false
Loop
{
Send, {Enter}
Sleep, 1000
if (stop)
{
break
}
}
break 是用来退出循环的,continue 是用来结束当前循环,进入下一次循环的。这和其他语言都一致。
二、Loop Until 循环
上边的最后一种用法,即满足某个条件时结束循环,也可以用 Until 来实现:
stop := false
Loop
{
Send, {Enter}
Sleep, 1000
}
Until stop
看起来比刚才的要简洁一些。
三、While 循环
有些时候我们需要先判断条件,然后再决定是否要循环,这样虽然用 Loop 也能实现,但有些别扭,这时就可以用 While 循环了。
count := 0
while (count < 10)
{
Send, {Enter}
Sleep, 1000
count++
}
和
count := 0
Loop
{
if (count >= 10)
{
break
}
Send, {Enter}
Sleep, 1000
count++
}
是等同的,使用哪个就看自己的习惯了。
四、for循环
例子:GB2312中文拼音排序
nameList := "
(
刘备
Washington
徐庶
Chen
A
a
张飞
Franklin
马良
魏延
诸葛亮
关羽
)"
MsgBox, % SortByPinyin(nameList, "`n", "`n")
SortByPinyin(str, deliIn := "`n", deliOut := "`n") {
; 拆分成数组
words := StrSplit(str, deliIn)
; 冒泡排序
loop % words.Length() - 1
loop % words.Length() - A_Index
if (PinyinCompare(words[A_Index], words[A_Index + 1]) > 0){
buf := words[A_Index]
words[A_Index] := words[A_Index + 1]
words[A_Index + 1] := buf
}
; 重新组合
for key, word in words
sorted .= deliOut word
return StrReplace(sorted, deliOut,,, 1)
}
PinyinCompare(str1, str2){
; 提供中英混排
static lowers := {"a": 45216.1, "b": 45252.1 ,"c": 45760.1, "d": 46317.1
, "e": 46825.1, "f": 47009.1, "g": 47296.1, "h": 47613.1, "i": 48118.1
, "j": 48118.3, "k": 49061.1, "l": 49323.1, "m": 49895.1, "n": 50370.1
, "o": 50613.1, "p": 50621.1, "q": 50905.1, "r": 51386.1, "s": 51445.1
, "t": 52217.1, "u": 52697.1, "v": 52697.3, "w": 52697.5, "x": 52979.1, "y": 53688.1, "z": 54480.1}
static uppers := {"A": 45216.2, "B": 45252.2, "C": 45761.2, "D": 46317.2
, "E": 46825.2, "F": 47009.2, "G": 47296.2, "H": 47613.2, "I": 48118.2
, "J": 48118.4, "K": 49061.2, "L": 49323.2, "M": 49895.2, "N": 50370.2
, "O": 50613.2, "P": 50621.2, "Q": 50905.2, "R": 51386.2, "S": 51445.2
, "T": 52217.2, "U": 52697.2, "V": 52697.4, "W": 52697.6, "X": 52979.2, "Y": 53688.2, "Z": 54480.2}
static capcity := VarSetCapacity(buf, 2)
; 拆分成单字对比
chars1 := StrSplit(Trim(str1, " `t`n")), chars2 := StrSplit(Trim(str2, " `t`n"))
loop % (chars1.Length() < chars2.Length()) ? chars1.Length() : chars2.Length() {
c1 := chars1[A_Index], c2 := chars2[A_Index]
if c1 is upper
code1 := uppers[c1]
else if c1 is lower
code1 := lowers[c1]
else {
StrPut(c1, &buf, 2, "cp936")
code1 := (NumGet(buf, 0, "UChar") << 8) + NumGet(buf, 1, "UChar")
}
if c2 is upper
code2 := uppers[c2]
else if c2 is lower
code2 := lowers[c2]
else {
StrPut(c2, &buf, "cp936")
code2 := (NumGet(buf, 0, "UChar") << 8) + NumGet(buf, 1, "UChar")
}
if (code1 != code2)
return code1 - code2
}
return chars1.Length - chars2.Length
}
五、更多内容
有些时候我们需要循环读取数组、读取字符串中的子字符串、读取文件内容、遍历目录下的文件甚至遍历注册表等,AHK 中都有很方便的用法,而无需让我们在 Loop 里写复杂的逻辑,我们会在之后的文章中了解到。
弱弱的请问,为何”a”: 45216.1, “b”: 45252.1 ,”c”: 45760.1, “d”: 46317.1……。英文字母对应的数字从何而来的?
请问,如果count为小于10,按一下回车,如果大于等于10,按一下左键,无论前面进行了多少次判定,只要累计按了10次左键,都将左边向右移动50像素,这个累计10次左键点击,要怎样加入循环?
a_index
请问,如果count为小于10,按一下回车,如果大于等于10,按一下左键,前面进行了多少次判定,只要累计按了10次左键,都将左边向右移动50像素,这个累计10次左键点击,要怎样加入循环?
这个好