AutoHotkey - 限制从字符串中提取的字符的数量和类型

问题描述

我有一个 IRC 客户端的 ahk 脚本,在文本字段中输入 nick!ident@host 并按 F4 后,它会解密 IP 地址的加密形式:

F4::
Clipboard =
Send ^a^x
Clipwait,0
If ErrorLevel
MsgBox,48,Error,An error occurred while waiting for the clipboard. Aborting.
Else Clipboard := decode(SubStr(Clipboard,-15,-8)) 
Return

decode(str) {
 Static code := " " "
 ( LTrim Join`s
 00 0x 02 03 04 0z 06 01 08 09 0B 0b 0c 0d 0e 0H x0 xx x2 x3 x4 xz x6 x1 x8 x9 xB xb xc xd xe xH 20 2x
 22 23 24 2z 26 21 28 29 2B 2b 2c 2d 2e 2H 30 3x 32 33 34 3z 36 31 38 39 3B 3b 3c 3d 3e 3H 40 4x 42 43
 44 4z 46 41 48 49 4B 4b 4c 4d 4e 4H z0 zx z2 z3 z4 zz z6 z1 z8 z9 zB zb zc zd ze zH 60 6x 62 63 64 6z
 66 61 68 69 6B 6b 6c 6d 6e 6H 10 1x 12 13 14 1z 16 11 18 19 1B 1b 1c 1d 1e 1H 80 8x 82 83 84 8z 86 81
 88 89 8B 8b 8c 8d 8e 8H 90 9x 92 93 94 9z 96 91 98 99 9B 9b 9c 9d 9e 9H B0 Bx B2 B3 B4 Bz B6 B1 B8 B9
 BB Bb Bc Bd Be BH b0 bx b2 b3 b4 bz b6 b1 b8 b9 bB bb bc bd be bH c0 cx c2 c3 c4 cz c6 c1 c8 c9 cB cb
 cc cd ce cH d0 dx d2 d3 d4 dz d6 d1 d8 d9 dB db dc dd de dH e0 ex e2 e3 e4 ez e6 e1 e8 e9 eB eb ec ed
 ee eH H0 Hx H2 H3 H4 Hz H6 H1 H8 H9 HB Hb Hc Hd He HH
 )"
 Loop,% StrLen(str) / 2
  new .= "." Round((Instr(code," " SubStr(str,2 * A_Index - 1,2),True) - 1) / 3)
 Return SubStr(new,2)
}

根据以下密钥进行解密:

https://pastebin.com/raw/P8cQtH2v

例如,对于用户数据,asdf!~z3040d4B@webchat 会将来自 z3040d4B 的 ident 解密为 83.4.13.75 并将此值复制到剪贴板。

但有些情况下,IP 的编码形式 (ident) 长于或短于 8 个字符或包含不在解密密钥中的字符。那么就不可能正确解码IP。因此,我希望脚本仅在检索到的字符串(在 !@ 之间,省略 ~ 符号(如果存在))长度为 8 个字符并且包含我输入的密钥中包含的字符。否则,脚本应清除剪贴板。怎么做?

解决方法

使用正则表达式 !~?[A-z\d]{8}@ 之类的正则表达式匹配方法肯定是最方便的:

F4::
    Clipboard := ""
    SendInput,^a^x
    ClipWait,0
    if (ErrorLevel)
        MsgBox,48,Error,An error occurred while waiting for the clipboard. Aborting.
    else if (Clipboard ~= "!~?[A-z\d]{8}@")
        Clipboard := decode(SubStr(Clipboard,-15,-8))
    else
        Clipboard := ""
Return

decode(str) 
{
    static code := " " "
    ( LTrim Join`s
    00 0x 02 03 04 0z 06 01 08 09 0B 0b 0c 0d 0e 0H x0 xx x2 x3 x4 xz x6 x1 x8 x9 xB xb xc xd xe xH 20 2x
    22 23 24 2z 26 21 28 29 2B 2b 2c 2d 2e 2H 30 3x 32 33 34 3z 36 31 38 39 3B 3b 3c 3d 3e 3H 40 4x 42 43
    44 4z 46 41 48 49 4B 4b 4c 4d 4e 4H z0 zx z2 z3 z4 zz z6 z1 z8 z9 zB zb zc zd ze zH 60 6x 62 63 64 6z
    66 61 68 69 6B 6b 6c 6d 6e 6H 10 1x 12 13 14 1z 16 11 18 19 1B 1b 1c 1d 1e 1H 80 8x 82 83 84 8z 86 81
    88 89 8B 8b 8c 8d 8e 8H 90 9x 92 93 94 9z 96 91 98 99 9B 9b 9c 9d 9e 9H B0 Bx B2 B3 B4 Bz B6 B1 B8 B9
    BB Bb Bc Bd Be BH b0 bx b2 b3 b4 bz b6 b1 b8 b9 bB bb bc bd be bH c0 cx c2 c3 c4 cz c6 c1 c8 c9 cB cb
    cc cd ce cH d0 dx d2 d3 d4 dz d6 d1 d8 d9 dB db dc dd de dH e0 ex e2 e3 e4 ez e6 e1 e8 e9 eB eb ec ed
    ee eH H0 Hx H2 H3 H4 Hz H6 H1 H8 H9 HB Hb Hc Hd He HH
    )"
    
    Loop,% StrLen(str) / 2
    {
        if (!InStr(code,block := " " SubStr(str,2 * A_Index - 1,2),true))
            return ""
        new .= "." Round((InStr(code,block,true) - 1) / 3)
    }
    return SubStr(new,2)
}

~=(docs)RegExMatch()(docs) 的简写。