2.14循环结构(loop、while、for)

在我们重复做一些事情的时候,就需要使用循环了。而 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 里写复杂的逻辑,我们会在之后的文章中了解到。

给TA捐赠
共{{data.count}}人
人已捐赠
其他

网页信息获取工具(web自动化编程必备工具之一,不断更新)

2018-11-11 23:01:44

其他案例

关机时运行命令[禁用windows Update的探索]

2018-12-6 20:52:43

4 条回复 A文章作者 M管理员
  1. 宝丰太平

    弱弱的请问,为何”a”: 45216.1, “b”: 45252.1 ,”c”: 45760.1, “d”: 46317.1……。英文字母对应的数字从何而来的?

  2. Kevin苏扬

    请问,如果count为小于10,按一下回车,如果大于等于10,按一下左键,无论前面进行了多少次判定,只要累计按了10次左键,都将左边向右移动50像素,这个累计10次左键点击,要怎样加入循环?

  3. Kevin苏扬

    请问,如果count为小于10,按一下回车,如果大于等于10,按一下左键,前面进行了多少次判定,只要累计按了10次左键,都将左边向右移动50像素,这个累计10次左键点击,要怎样加入循环?

  4. ccc

    这个好

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索