AutoHotkey Expression Examples: "" %% () and all that. Good for beginners.
AutoHotkey Expression Examples: "" %% () and all that.
because I can never get them right, so I made this. These are all working examples. Version 1.21c 08/24/2009
[source: http://www.daviddeley.com/autohotkey/xprxmp/autohotkey_expression_examples.htm#K]
CONTENTS:
A: | RETRIEVING COMMAND LINE PARAMETERS | ||||||||||||||||||
B: | COMMON THINGS AT THE BEGINNING AND END OF AUTOHOTKEY SCRIPTS | ||||||||||||||||||
C: | WHEN TO USE %% AROUND VARIABLES | ||||||||||||||||||
D: | ERASE A VARIABLE | ||||||||||||||||||
E: | SET A VARIABLE := [store numbers, quoted strings] | ||||||||||||||||||
F: | SET A VARIABLE = [assign unquoted literal strings] | ||||||||||||||||||
G: | COPY A VARIABLE | ||||||||||||||||||
H: | IF STATEMENTS with () | ||||||||||||||||||
H2: Comparing Numeric Values vs. Comparing Strings | |||||||||||||||||||
I: | IF STATEMENTS without () [Translate the 1st, take the 2nd literally] | ||||||||||||||||||
I2: Comparing Numeric Values vs. Comparing Strings | |||||||||||||||||||
J: | CHECK FOR A BLANK VARIABLE | ||||||||||||||||||
K: | STRING MANIPULATION
|
||||||||||||||||||
L: | NUMBERS
|
||||||||||||||||||
M: | working with FILE NAMES | ||||||||||||||||||
N: | REGULAR EXPRESSIONS
|
||||||||||||||||||
O: | MISC AUTOHOTKEY NOTES. CAVEATS & DEBUGGING TIPS
|
||||||||||||||||||
P: | MISC AUTOHOTKEY SCRIPTS
|
||||||||||||||||||
Q: | NAVIGATING WEB SITES
|
||||||||||||||||||
R: | NEWBIE RECOMMENDED LEARNING SEQUENCE | ||||||||||||||||||
S: | Press ESC to cancel this scipt | ||||||||||||||||||
T: | THE AUTOHOTKEY RUN COMMAND | ||||||||||||||||||
U: | PASSING PARAMETERS TO AUTOHOTKEY SCRIPTS | ||||||||||||||||||
V: | PASSING PARAMETERS TO ANY PROGRAM |
/******************************************************************************
NOTE: | ALL VARIABLES ARE STORED AS CHARACTER STRINGS !!! Strings containing numbers are converted to numbers when needed, and the result is converted back to a string. |
NOTE: | Closing */ must be first thing on line. Otherwise you'll be asking yourself, "Why does my script stop running at this point, as if the whole rest of the script was commented out?" |
/******************************************************************************
A: PASSING COMMAND LINE PARAMETERS TO AN AUTOHOTKEY SCRIPT
- Arguments are delimited by white space, which is either a space or a tab.
- The caret character (^) is not recognized as an escape character or delimiter. The character is handled completely by the command-line parser in the operating system before being passed to the argv array in the program.
- A string surrounded by double quotation marks ("string") is interpreted as a single argument, regardless of white space contained within. A quoted string can be embedded in an argument.
- A double quotation mark preceded by a backslash (\") is interpreted as a literal double quotation mark character (").
- Backslashes are interpreted literally, unless they immediately precede a double quotation mark.
- If an even number of backslashes is followed by a double quotation mark, one backslash is placed in the argv array for every pair of backslashes, and the double quotation mark is interpreted as a string delimiter.
- If an odd number of backslashes is followed by a double quotation mark, one backslash is placed in the argv array for every pair of backslashes, and the double quotation mark is "escaped" by the remaining backslash, causing a literal double quotation mark (") to be placed in argv.
- Tech note on passing command line parameters to any program
A: RETRIEVING COMMAND LINE PARAMETERS
NumParams = %0% Param1 = %1% Param2 = %2% Param3 = %3% MsgBox NumParams = %0% MsgBox Param1 = %1% MsgBox Param2 = %2% MsgBox Param3 = %3%
/******************************************************************************
B: COMMON THINGS OFTEN FOUND AT THE BEGINNING OF AUTOHOTKEY SCRIPTS
#NoTrayIcon ;if you don't want a tray icon for this AutoHotkey program. #NoEnv ;Recommended for performance and compatibility with future AutoHotkey releases. #SingleInstance force ;Skips the dialog box and replaces the old instance automatically ;;SendMode Input ;I discovered this causes MouseMove to jump as if Speed was 0. (was Recommended for new scripts due to its superior speed and reliability.) SetKeyDelay, 90 ;Any number you want (milliseconds) CoordMode,Mouse,Screen ;Initial state is Relative CoordMode,Pixel,Screen ;Initial state is Relative. Frustration awaits if you set Mouse to Screen and then use GetPixelColor because you forgot this line. There are separate ones for: Mouse, Pixel, ToolTip, Menu, Caret MouseGetPos, xpos, ypos ;Save initial position of mouse WinGet, SavedWinId, ID, A ;Save our current active window ;Set Up a Log File: SetWorkingDir, %A_ScriptDir% ;Set default directory to where this script file is located. (Note %% because it's expecting and unquoted string) LogFile := "MyLog.txt" FileAppend, This is a message`n, %LogFile% ;Note the trailing (`n) to start a new line. This could instead be a leading (`n) if you want. (Note %% because it's expecting and unquoted string)
and things at the end where we restore window and mouse cursor position:
WinActivate ahk_id %SavedWinId% ;Restore original window MouseMove, xpos, ypos, 10 ;Restore original mouse position ExitApp Esc::ExitApp ;Press ESC to cancel this script. Placed after the ExitApp. ;Note this is a hotkey definition (we're defining the ESC key to run ExitApp). A ;hotkey definition line stops execution at that point, so if you want the script ;to run to the end but have the ESC key available to terminate the script, put ;the hotkey definition at the end, just after your ExitApp statement.
/******************************************************************************
C: WHEN TO USE %% AROUND VARIABLES
LESSON #1:
The only place to use %x% is where a literal string NOT enclosed in double-quotes is expected. Otherwise, don't use %% around a variable name.
Notice in the following examples that unquoted literal strings are expected.
( = assigns unquoted literal strings )
n = Ishmael x = Call me %n% MsgBox %x% x = 500 y = 500 z = 10 MouseMove, 500, 500, 10 ;works MouseMove, 500 - 1, 500 + 1, 10 ;works MouseMove, x, y, z ;works MouseMove, x - 1, y + 1, z + 2 ;works ;However, this doesn't work, because MouseMove ;doesn't expect an unquoted literal string MouseMove, %x% - 1, %y% + 1, 10 ;doesn't work
Confusion is caused because the following also happens to work:
MouseMove, %x%, %y%, %c% ;works because "for backward compatibility, command parameters that are ;documented as 'can be an expression' treat an isolated name in percent signs ;(e.g. %Var%, but not Array%i%) as though the percent signs are absent." ; --AutoHotkey Documentation: Variables and Expressions
LESSON #2:
Use (%x%) (enclosed in parentheses) when x contains the name of a 2nd variable which in turn contains the contents you want.
a = 500 ;a = "500" b = 200 ;b = "200" x := "a" y := "b" MouseMove, (%x%), (%y%) ;x = a, a = 500. y = b, b = 200 MouseGetPos, xpos, ypos MsgBox xpos=%xpos% ypos=%ypos% ;xpos=500 ypos=200
LESSON #3:
Instances which look like exceptions to the rule:
MyDocument := "C:\Program Files\AutoHotkey\license.txt" Run, notepad.exe "%MyDocument%"
Looks like we're using %% inside a quoted string, but actually the "" are not required, just recommended. This happens to also work:
Run, notepad.exe %MyDocument%
The run function expects an unquoted string, so we use %%, otherwise notepad would try to open a file named 'MyDocument'.
In the first case above, the run function is actually accepting an unquoted string which happens to begin and end with a double quote character.
Tech Note I believe the Target string in the AutoHotkey Run command is passed as the command_line parameter to the Windows CreateProcess() function. I see in AutoHotkey source file script.cpp routine Script::ActionExec the call to CreateProcess is: if (CreateProcess(NULL, command_line, NULL, NULL, FALSE, 0, NULL, aWorkingDir, &si, &pi))MSDN documentaion for CreateProcess says, "If you are using a long file name that contains a space, use quoted strings to indicate where the file name ends and the arguments begin." So the beginning and ending double quote characters are actually a part of the string being passed. (05/29/2009 — I'm testing how AutoHotkey parses the Run command. I'll post the results when I'm done.) Reference: CreateProcess() : http://msdn.microsoft.com/en-us/library/ms682425.aspx CreateProcess() : http://msdn.microsoft.com/en-us/library/ms682425(VS.85).aspx |
/******************************************************************************
D: ERASE A VARIABLE
v = v := ""
/******************************************************************************
E: SET A VARIABLE (:=)
Use the colon-equal operator (:=) for storing numbers and quoted strings
NOTE: All variables including numbers are stored as character strings. Strings are automatically converted to numbers when necessary, then converted back to strings when result is stored in a variable.
ABC := "David" David := "Susan" v := "ABC" ; v = "ABC" MsgBox v := "ABC"`n`nv = "%v%" v := ABC ; ABC is a variable. v = "David" MsgBox v := ABC`n`nv = "%v%" v := %ABC% ; ABC is a variable containing the name of a variable. v = "Susan" MsgBox v := `%ABC`%`n`nv="%v%" ; NOTE: If ABC is undefined or blank, program halts! v := "123" ; v = "123" (quotes NOT included) MsgBox v := "123"`n`nv = "%v%" v := 123 ; v = "123" (If it can be interpreted as a number then it's a number, otherwise it's a variable name.) MsgBox v := 123`n`nv = "%v%" ;123 can be made into a variable, as in this horrendous example: 123 := 456 MsgBox v = %123% ; message is "v = 456"
/******************************************************************************
F: SET A VARIABLE (=)
equal sign operator (=) to assign unquoted literal strings
To include variable ABC instead of literal string "ABC", use %ABC%
ABC = David David = Susan v = 123 ;v = "123" MsgBox v = 123`n`nv = "%v%" v = 0001 ;v = "0001" MsgBox v = 0001`n`nv = "%v%" v = ABC ;v = "ABC" MsgBox v = ABC`n`nv = "%v%" v = %ABC% ;ABC is a variable. v = "David" MsgBox v = `%ABC`%`n`nv = "%v%" (ABC = "David") ;PROBABLY NOT WHAT YOU WANTED: v = "ABC" ;v = the literal string "ABC" (including double-quotes) MsgBox v = "ABC"`n`nv = '%v%'
/******************************************************************************
G: COPY A VARIABLE
ABC := "David" David := "Susan" v := ABC ; ABC is a variable. v = "David" MsgBox v := ABC`n`nv = "%v%" v = %ABC% ; ABC is a variable. v = "David" MsgBox v = `%ABC`%`n`nv = "%v%" ;PROBABLY NOT WHAT YOU WANTED: v = ABC ; v = "ABC" (the literal string) MsgBox v = ABC`n`nv = "%v%" v := %ABC% ; ABC is a variable containing the name of a variable. v = "Susan" MsgBox v := `%ABC`%`n`nv="%v%" ; NOTE: If ABC is undefined, PROGRAM HALTS! (If David is undefined, then v = "")
/******************************************************************************
H: IF STATEMENTS with ()
SAT := "Saturday" ;Another way to view this is: Saturday := "Saturn" ; SAT --> Saturday --> Saturn MON := "Monday" ; MON --> Monday --> Moon Monday := "Moon" MsgBox SAT := "Saturday"`nSaturday := "Saturn"`nMON := "Monday"`nMonday := "Moon"`n`n(another way to view this:)`nSAT --> Saturday --> Saturn`nMON --> Monday --> Moon`n`n#16 ; = If ("Saturday" = "Saturday") MsgBox ("Saturday" = "Saturday") If ("Saturday" = "SATURDAY") MsgBox ("Saturday" = "SATURDAY") ; == (case sensitive compare) If ("Saturday" == "Saturday") ;== Case Sensitive MsgBox ("Saturday" == "Saturday") If ("Saturday" == "SATURDAY") ;== Case Sensitive MsgBox NO ;SAT = "Saturday" If (SAT = "Saturday") ;SAT = "Saturday", compare with "Saturday" MsgBox (SAT = "Saturday") If ("Saturday" = SAT) ;Reverse works the same MsgBox ("Saturday" = SAT) If (SAT = "xxxxx") MsgBox NO If ("xxxxx" = SAT) MsgBox NO ;%SAT% = "Saturn" If ("Saturn" = "Saturn") MsgBox ("Saturn" = "Saturn") If (%SAT% = "Saturn") ;SAT = "Saturday", %SAT% = "Saturn", compare with "Saturn" (no problem if SAT not defined) MsgBox (`%SAT`% = "Saturn")`n`n(no problem if SAT not defined) If ("Saturn" = %SAT%) ;Reverse works the same (no problem if SAT not defined) MsgBox ("Saturn" = `%SAT`%)`n`n(no problem if SAT not defined) If ("xxxxx" = %SAT%) ;compare "xxxxx" with "Saturn" MsgBox NO If (%SAT% = "xxxxx") ;compare "Saturn" with "xxxxx" MsgBox NO ;"Moon" = %MON% If ("Moon" = "Moon") MsgBox ("Moon" = "Moon") If (%MON% = "Moon") ;MON = "Monday", Monday = "Moon", compare with "Moon" (no problem if MON not defined) MsgBox (%MON% = "Moon")`n`nMON = "Monday", Monday = "Moon", compare with "Moon"`n`n(no problem if MON not defined) If ("Moon" = %MON%) ;"Moon", compare with MON = "Monday", Monday = "Moon" (no problem if MON not defined) MsgBox ("Moon" = `%MON`%)`n`n"Moon", compare with MON = "Monday", Monday = "Moon"`n`n(no problem if MON not defined) If ("xxxxx" = %MON%) ;compare "xxxxx" with "Moon" MsgBox NO If (%MON% = "xxxxx") ;compare "Moon" with "xxxxx" MsgBox NO ;SAT =? MON If (SAT = MON) ;Compare "Saturday" = "Monday" [SAT = "Saturday", MON = "Monday"] MsgBox NO If (SAT < MON) ;"Saturday" < "Moon" MsgBox NO If (SAT > MON) ;"Saturday" > "Moon" [S > M] MsgBox (SAT > MON)`n`n"Saturday" > "Monday"`n`n[S > M] ;SAT =? %MON% If (SAT = %MON%) ;Compare "Saturday" = "Moon". [SAT = "Saturday", compare with MON = "Monday", Monday = "Moon"] MsgBox NO If (SAT < %MON%) ;"Saturday" < "Moon" MsgBox NO If (SAT > %MON%) ;"Saturday" > "Moon" [S > M] MsgBox (SAT > `%MON`%)`n`n"Saturday" > "Moon" [S > M]`n`nSAT = "%SAT%",`nMON = "%MON%", %MON% = "Moon" ;%SAT% =? MON If (%SAT% = MON) ;Compare "Saturn" = "Monday". [SAT = "Saturday", Saturday = "Saturn", MON = "Monday"] MsgBox NO If (%SAT% < MON) ;"Saturn" < "Monday" MsgBox NO If (%SAT% > MON) ;"Saturn" > "Monday" [S > M] MsgBox (`%SAT`% > MON)`n`nSAT = "Saturday", %SAT% = "Saturn", compare with MON = "Monday"`n`n"Saturn" > "Moon"`n`n[S > M] ;%SAT% =? %MON% If (%SAT% = %MON%) ;Compare "Saturn" = "Moon". [SAT = "Saturday", Saturday = "Saturn", compare with MON = "Monday", Monday = "Moon"] MsgBox NO If (%SAT% < %MON%) ;"Saturn" < "Moon" MsgBox NO If (%SAT% > %MON%) ;"Saturn" > "Moon" [S > M] MsgBox (`%SAT`% > `%MON`%)`n`nSAT = "Saturday", %SAT% = "Saturn", compare with`nMON = "Monday", %MON% = "Moon"`n`n"Saturn" > "Moon"`n`n[S > M]
H2: Comparing Numeric Values vs. Comparing Strings
If they can both be interpreted as numbers, then they are compared as numbers. Otherwise they are compared as strings.
;COMPARING NUMERIC VALUES VS. COMPARING STRINGS if statements with () x = 05 ; x = "05" if (x > 3.14) ; (5 > 3.14) ? Compare numeric values, since both can be interpreted as numeric values. MsgBox if (x > 3.14)`nwith x = "05"`n`nCompare numeric values, since both "05" and "3.14" can be interpreted as numbers.`n(5 > 3.14) ?`nyes else MsgBox xxxxxx if (x > "3.14") ; ("05" > "3.14") ? Compare strings, since "3.14" is explicitly a string. (The " " around 3.14 say it's a string, not a number, so do a string compare.) MsgBox xxxxxx else MsgBox if (x > "3.14")`nwith x = "05"`n`nCompare strings, since "3.14" is explicitly a string.`nThe " " around "3.14" say it's a string, not a number, so do a string compare.`n("05" > "3.14") ?`n("0" > "3") ?`n(48 > 51) ?`nno ; ASCII table: ; / 47 ; 0 48 ; 1 49 ; 2 50 ; 3 51 ; 4 52 ; 5 53 ; 6 54 ; 7 55 ; 8 56 ; 9 57 ; : 58 ;DEREFERENCE TESTS y := "x" ;Compare %y% with 3.14 x = 03 ; x = "03" if (%y% > 3.14) ; (3 > 3.14) ? MsgBox xxxxxx else MsgBox if (`%y`% > 3.14)`nwith y = "x"`nand x = "03"`n`nCompare numeric values, since both "03" and "3.14" can be interpreted as numbers.`n(3 > 3.14) ?`nno x = 05 ; x = "05" if (%y% > 3.14) ; (5 > 3.14) ? MsgBox if (`%y`% > 3.14)`nwith y = "x"`nand x = "05"`n`nCompare numeric values, since both "05" and "3.14" can be interpreted as numbers.`n(5 > 3.14) ?`nyes else MsgBox NO ;Compare %y% with "3.14" x = 03 ; x = "03" if (%y% > "3.14") ; ("03" > "3.14") ? MsgBox xxxxxx else MsgBox if (`%y`% > "3.14")`nwith y = "x"`nand x = "03"`n`nCompare strings, since "3.14" is explicitly a string.`nThe " " around "3.14" say it's a string, not a number, so do a string compare.`n("03" > "3.14") ?`n("0" > "3") ?`n(48 > 51) ?`nno x = 05 ; x = "05" if (%y% > "3.14") ; ("05" > "3.14") ? MsgBox xxxxxx else MsgBox if (`%y`% > "3.14")`nwith y = "x"`nand x = "05"`n`nCompare strings, since "3.14" is explicitly a string.`nThe " " around "3.14" say it's a string, not a number, so do a string compare.`n("05" > "3.14") ?`n("0" > "3") ?`n(48 > 51) ?`nno x := "/" ; x = "/" if (%y% > "3.14") ; ("/" > "3.14") ? MsgBox xxxxxx else MsgBox if (`%y`% > "3.14")`nwith y = "x"`nand x = "/"`n`nCompare strings, since "3.14" is explicitly a string.`nThe " " around "3.14" say it's a string, not a number, so do a string compare.`n("/" > "3.14") ?`n("/" > "3") ?`n(47 > 51) ?`nno x := ":" ; x = ":" if (%y% > "3.14") ; (":" > "3.14") ? MsgBox if (`%y`% > "3.14")`nwith y = "x"`nand x = ":"`n`nCompare strings, since "3.14" is explicitly a string.`nThe " " around "3.14" say it's a string, not a number, so do a string compare.`n(":" > "3.14") ?`n(":" > "3") ?`n(58 > 51) ?`nyes else MsgBox xxxxxx
/******************************************************************************
I: IF STATEMENTS without ()
Translate the 1st, take the 2nd literally
SAT := "Saturday" ;Another way to view this is: Saturday := "Saturn" ; SAT --> Saturday --> Saturn MON := "Monday" ; MON --> Monday --> Moon Monday := "Moon" MsgBox SAT := "Saturday"`nSaturday := "Saturn"`nMON := "Monday"`nMonday := "Moon"`n`n(another way to view this:)`nSAT --> Saturday --> Saturn`nMON --> Monday --> Moon ;SAT ; If "Saturday" = .... illegal If SAT = Saturday ;SAT = "Saturday", compare with "Saturday" MsgBox If SAT = Saturday`n`nSaturday = Saturday If SAT = %Saturday% ;SAT = "Saturday", compare with %Saturday% = "Saturn" MsgBox NO If SAT = SAT ;SAT = "Saturday", compare with "SAT" MsgBox NO If SAT = %SAT% ;SAT = "Saturday", compare with %SAT% = "Saturday" MsgBox If SAT = `%SAT`%`n`nSaturday = Saturday ;%SAT% ;NOTE: if SAT is undefined or blank, program will halt! If %SAT% = Saturn ;SAT = "Saturday", Saturday = "Saturn", compare with "Saturn" MsgBox If `%SAT`% = Saturn`n`nSAT = "%SAT%", `%Saturday`% = %Saturday%, compare with "Saturn"`n`n(Note: if SAT is undefined or blank, program will halt!) If %SAT% = xxxxx ;SAT = "Saturday", Saturday = "Saturn", compare with "xxxxx" MsgBox NO ;Saturday If Saturday = Saturn ;Saturday = "Saturn", compare with "Saturn" MsgBox Saturday = Saturn`n`nSaturday="%Saturday%",compare with "Saturn" If Saturday = xxxxx ;Saturday = "Saturn", compare with "xxxxx" MsgBox NO ;%Saturday% ;NOTE: if SATURDAY is undefined or blank, program will halt! If %Saturday% = ;Saturday = "Saturn", Saturn = <nothing>, compare with <nothing> MsgBox If `%Saturday`% = `n`nSaturday=%Saturday%, Saturn=<nothing>, compare with <nothing>`n`n(NOTE: if SATURDAY is undefined or blank, program will halt!) If %Saturday% = %Saturn% ;Saturday = "Saturn", Saturn = <nothing>, compare with %Saturn% = <nothing> (<nothing> = <nothing>) MsgBox if `%Saturday`% = `%Saturn`%`n`nSaturday=%Saturday%, Saturn=<nothing>`ncompare with`%Saturn`% = <nothing>`n`n<nothing>=<nothing> If %Saturday% = xxxxx ;Saturday = "Saturn", Saturn = <nothing>, compare with "xxxxx" MsgBox NO If %Saturday% = "" ;Saturday = "Saturn", Saturn = <nothing>, compare with literal two double-quotes (a string containing two characters, both double-quotes) MsgBox NO
I2: Comparing Numeric Values vs. Comparing Strings
If they can both be interpreted as numbers, then they are compared as numbers. Otherwise they are compared as strings.
I2: ;COMPARING NUMERIC VALUES VS. COMPARING STRINGS if statements without () ; ASCII table: ; ! 33 ; " 34 ; # 35 ; 0 48 x = 03 ; x = "03" if x > 3.14 ; 3 > 3.14 (Compare numeric values, since both can be interpreted as numeric values) MsgBox xxxxxx else MsgBox if x > 3.14`nwith x=%x%`n`nCompare numeric values, since both can be interpreted as numeric values`n3 > 3.14 ?`nno x = 05 ; x = "05" if x > 3.14 ; 5 > 3.14 (Compare numeric values, since both can be interpreted as numeric values) MsgBox if x > 3.14`nwith x=%x%`n`nCompare numeric values, since both can be interpreted as numeric values`n5 > 3.14 ?`nyes else MsgBox xxxxxx x = 03 ; x = "03" if x > "3.14" ; compare string '03' with string '"3.14"' (double quotes are part of the string). Compare ascii 0 in 03 with leading quotation mark in "3.14" (48 > 34 ?) Yes. MsgBox if x > "3.14"`nwith x=%x%`n`nDouble quotes are part of the string "3.14"`nso string compare 03 with "3.14"`ncompare leading '0' in 03 with leading quotation mark in "3.14"`nascii(0) = 48`nascii(") = 34`n48 > 34 (?)`nyes else MsgBox xxxxxx x = ! ; x = '!' (ascii 33) if x > "3.14" ;compare string '!' with string '"3.14"' (double quotes are part of the string). Compare ascii ! with leading quotation mark in "3.14" (48 > 34 ?) Yes. ; (! > ")? --> (33 > 34) ? no MsgBox xxxxxx else MsgBox if x > "3.14"`nwith x=%x%`nno`n`ncompare ascii ! with leading quotation mark in "3.14"`nascii(!) = 33`nascii(") = 34`n(33 > 34)?`nno x = # ; x = '#' (ascii 35) if x > "3.14" ; (! > ")? --> (35 > 34) ? yes MsgBox if x > "3.14"`nwith x=%x%`nyes`n`ncompare ascii # with leading quotation mark in "3.14"`nascii(#) = 35`nascii(") = 34`n(35 > 34)?`nyes else MsgBox xxxxxx ; ASCII table: ; ! 33 ; " 34 ; # 35 ; 0 48 ;DEREFERENCE TESTS y := "x" ;compare %y% with 3.14 x = 03 ; x = "03" if %y% > 3.14 ; 3 > 3.14 (?) MsgBox xxxxxx else MsgBox if `%y`% > 3.14`nwith y := "x"`nand x = "03"`n`nCompare numeric values, since both "03" and "3.14" can be interpreted as numbers.`n3 > 3.14 (?)`nno x = 05 ; x = "05" if %y% > 3.14 ; 5 > 3.14 (?) MsgBox if `%y`% > 3.14`nwith y := "x"`nand x = "05"`n`nCompare numeric values, since both "05" and "3.14" can be interpreted as numbers.`n5 > 3.14 (?)`nyes else MsgBox xxxxxx ;compare %y% with "3.14" x = 03 ; x = "03" if %y% > "3.14" ; Double quotes are part of the string "3.14" so string compare '03' with string '"3.14"'. Compare ascii 0 in 03 with leading quotation mark in "3.14" (48 > 34 ?) Yes. MsgBox if `%y`% > "3.14"`nwith y := "x"`nand x=%x%`n`nDouble quotes are part of the string "3.14"`nso string compare 03 with "3.14"`ncompare leading '0' in 03 with leading quotation mark in "3.14"`nascii(0) = 48`nascii(") = 34`n48 > 34 (?)`nyes else MsgBox xxxxxx x = ! ; x = '!' (ascii 33) if x > "3.14" ;Double quotes are part of the string "3.14" so string compare '!' with string '"3.14"'. Compare '!' with leading quotation mark in "3.14" (48 > 34 ?) Yes. MsgBox xxxxxx else MsgBox if `%y`% > "3.14"`nwith y := "x"`nand x=%x%`n`nDouble quotes are part of the string "3.14"`nso string compare ! with "3.14"`ncompare '!' with leading quotation mark in "3.14"`nascii(!) = 33`nascii(") = 34`n33 > 34 (?)`nno x = # ; x = '#' (ascii 35) if x > "3.14" ; (! > ")? --> (35 > 34) ? yes MsgBox if `%y`% > "3.14"`nwith y := "x"`nand x=%x%`n`nDouble quotes are part of the string "3.14"`nso string compare # with "3.14"`ncompare '#' with leading quotation mark in "3.14"`nascii(#) = 35`nascii(") = 34`n35 > 34 (?)`nyes else MsgBox xxxxxx
/******************************************************************************
J: CHECK FOR A BLANK VARIABLE
(or undefined variable)
v := "" If v = MsgBox v = "" If (v = "") MsgBox v = ""
/******************************************************************************
K: STRING MANIPULATION
K1: Trim whitespace at the START of a string
;Trim whitespace at the START of a string: v := " 0001 " MsgBox v="%v%" v := RegExReplace( v, "\A\s+" ) MsgBox v="%v%" ;v = "0001 "
K2: Trim whitespace at the END of a string
;Trim whitespace at the END of a string: v := " 0001 " MsgBox v="%v%" v := RegExReplace( v, "\s+\z" ) MsgBox v="%v%" ;v = " 0001"
K3: Trim whitespace at the START AND END of a string
K3a:
;Trim whitespace at the START AND END of a string: v := " 0001 " MsgBox v="%v%" v := RegExReplace( v, "(^\s+)|(\s+$)") MsgBox v="%v%" ;v = "0001"
;Trim whitespace at the START AND END of the string: v := " 0001 " MsgBox v="%v%" v = %v% ;v = "0001" (AutoTrim ON by default) MsgBox v="%v%"
K4: Concatenate Two Strings Together
;CONCATENATE TWO STRINGS TOGETHER SAT := "Saturday" MON := "Monday" Saturday := "Saturn" Monday := "Moon" ; using = v = %SAT%%MON% ; v = "SaturdayMonday" MsgBox v = "%v%" ; using := v := "Saturday" . "Monday" ; v = "SaturdayMonday" MsgBox v = "%v%" v := SAT . MON ; v = "SaturdayMonday" (there must be a SPACE before and after dot) MsgBox v = "%v%" v := %SAT% . MON ; v = "SaturnMonday" MsgBox v = "%v%" v := SAT . %MON% ; v = "SaturdayMoon" MsgBox v = "%v%" v := %SAT% . %MON% ; v = "SaturnMoon" MsgBox v = "%v%"
K5: Two ways of using MsgBox
This is a good place to mention the two ways of using MsgBox:
Msgbox Var = %Var% ; OR Msgbox % "Var = " . Var ; string-^^^^^^ | ^^^-variable name ; Concatenate
K6:
SEE ALSO:
Library for Text File Manipulation
http://www.autohotkey.net/~heresy/Functions/TXT.ahk
/******************************************************************************
L: NUMBERS
NOTE: All variables are stored as character strings.
Strings are automatically converted to numbers when necessary,
then converted back to strings when result is stored in a variable.
L1: Adding numbers together
;Adding numbers together v := "123" v += 1 MsgBox v = "%v%" ; v <- "124" v := "123" v := v + 1 MsgBox v = "%v%" ; v <- "124" ;PROBABLY NOT WHAT YOU WANTED: v = 123 ; v <- "123" (the literal string) v = v + 1 ; v <- "v + 1" (the literal string) MsgBox v = "%v%"
L2: Adding two strings together
;Adding two strings together ;when both can be interpreted as integers, gives the resulting integer (as a string) v1 := 123 v2 := 456 v := v1 + v2 ; v <- "579" MsgBox v = "%v%" ;when one or both can be interpreted as float, gives the resulting float (as a string) v1 := 1.23 v2 := 45.6 v := v1 + v2 ; v <- "46.830000" MsgBox v = "%v%" ;When one or both can NOT be interpreted as a number, result is an empty string v1 := "123" v2 := "Susan" v := v1 + v2 ; v <- "" (empty string) MsgBox v = "%v%"
L3: Remove leading/trailing blanks/zeros from a number
;Remove leading zeros from a number v := 0001 ;v = "0001" v += 0 ;v converted to integer, add zero, convert back to string MsgBox v = "%v%" ;v = "1" (the literal string "1" ;Remove leading blanks and trailing blanks from a number v := " 1 " MsgBox v = "%v%" ;v = " 1 " v += 0 ;v converted to integer, add zero, convert back to string MsgBox v = "%v%" ;v = "1" (the literal string "1" ;Remove leading and trailing blanks and leading zeros from a number v := " 0001 " MsgBox v = "%v%" ;v = " 0001 " v += 0 ;v converted to integer, add zero, convert back to string MsgBox v = "%v%" ;v = "1" (the literal string "1" ;(yea it's all the same. Just do v += 0)
L4: Pad a number with leading zeros or spaces
/************************************************
VARIOUS WAYS TO PAD A NUMBER WITH LEADING ZEROS OR SPACES
(To pad with spaces, substitute spaces for the zeros.)
L4.1: Method #1: SubStr
;PAD A NUMBER WITH LEADING ZEROS OR SPACES — Method #1: SUBSTR ; Documentation on SubStr: "If StartingPos is less than 1, it is ; considered to be an offset from the end of the string. For example, 0 ; extracts the last character and -1 extracts the two last characters." v := 123 ;....v....1 ....v....1 v := SubStr("0000000000" . v, -9) ; v = "0000000123" MsgBox v = "%v%" v := SubStr("abcdefghij" . v, -9) ; v = "defghij123" (easier to see what's happening) MsgBox v = "%v%"
;PAD A NUMBER WITH LEADING ZEROS OR SPACES — Method #2: StringRight v := 123 ;....v....1 ....v....1... v := "0000000000" . v ; v = "0000000000123" ( or could use v = "0000000000"%v% ) StringRight, v, v, 10 ; v = "0000000123" MsgBox v = "%v%"
;PAD A NUMBER WITH LEADING ZEROS OR SPACES — Method #3: sprintf() StrIn := "1234" size := VarSetCapacity(StrOut, 8) ;want StrOut to hold 8 digits ;pad with zeros DllCall("msvcrt\sprintf", Str, StrOut, Str, "%08d", "Int", StrIn ) ;pad with zeros MsgBox, 0, Zeros, size=%size%`nStrIn = %StrIn%`nStrOut = %StrOut% ;StrOut = "00000123" ;pad with blanks DllCall("msvcrt\sprintf", Str, StrOut, Str, "%8d", "Int", StrIn ) ;pad with blanks MsgBox, 0, Spaces, size=%size%`nStrIn = %StrIn%`nStrOut = %StrOut% ;StrOut = " 123"
L4.4: Method #4: Prepend leading zeros
;PAD A NUMBER WITH LEADING ZEROS OR SPACES — Method #4: Prepend leading zeros v = 123 Loop, % 9-StrLen(v) ; (9 for 9 digits total) v = 0%v% ; OR: v := 0 . v MsgBox, 0, Zeros, v = "%v%" ; v = "000000123" ;Prepend leading spaces v = 123 Loop, % 9-StrLen(v) ; (9 for 9 digits & spaces total) v := A_Space . v ; OR: v := " " . v MsgBox, 0, Spaces, v = "%v%" ; v = " 123"
;PAD A NUMBER WITH LEADING ZEROS OR SPACES — Method #5: Using SetFormat ;(Note: Be wary of converting an integer to a float and back to an integer. ; An integer has 32 bits of data, whereas a float has only 27 bits of data.) v = 1234 SetFormat, Float, 08.0 ; (08 for zero padded 8 digits total, .0 for zero decimal places) v += 0.0 ; v converted to float, add zero, convert back to string MsgBox v = %v% ; v = '00001234' v = 1234 SetFormat, Float, 8.0 ; (8 for space padded 8 digits & spaces total, .0 for zero decimal places) v += 0.0 ; v converted to float, add zero, convert back to string MsgBox v = %v% ; v = ' 1234'
/******************************************************************************
M: working with FILE NAMES
;Set/Show Working Directory SetWorkingDir,%A_ScriptDir% MsgBox A_WorkingDir=%A_WorkingDir% ;Creating a File (note: directory must exist) FileAppend, test 10, MyFile10.log ;<WorkingDir>\MyFile10.log FileAppend, test 11, \MyFile11.log ;C:\MyFile11.log FileAppend, test 12, SubDir\MyFile12.log ;<WorkingDir>\SubDir\MyFile12.log FileAppend, test 13, SubDir\\\\\\\\\\\\\MyFile13.log ;<WorkingDir>\SubDir\MyFile13.log Doesn't seem to matter how many extra \ V := "C:\TEMP" FileAppend, test 14, %V%MyFile14.log ;C:\TEMPMyFile14.log FileAppend, test 15, %V%\MyFile15.log ;C:\TEMP\MyFile15.log FileAppend, test 16, %V%\\\\\\\\\\\MyFile16.log ;C:\TEMP\MyFile16.log Doesn't seem to matter how many extra \ FileAppend, test 17, ..\MyFile17.log ;Up one directory from WorkingDir. <WorkingDir-^>\MyFile17.log MsgBox ErrorLevel=%ErrorLevel% ;FileAppend test for error. 0=SUCCESS, 1=FAIL
/******************************************************************************
N: REGULAR EXPRESSIONS
(Note: AutoHotkey uses PCRE Perl-compatible format)
N1: Regular Expression RESOURCES
CHEAT SHEETS
Regular Expressions (RegEx) - Quick Reference: http://www.autohotkey.com/docs/misc/RegEx-QuickRef.htm
Regular Expression Cheat Sheet: http://regexlib.com/CheatSheet.aspx
One Page Reference Cheat Sheet: http://www.regular-expressions.info/reference.html
Replacement Text Reference: http://www.regular-expressions.info/refreplace.html
HEAVY DOCUMENTATION
Syntax of regular expressions in Perl: http://search.cpan.org/dist/perl/pod/perlre.pod
Syntax of regular expressions in Perl: http://perldoc.perl.org/perlre.html
Concatenation of the PCRE man pages: http://www.pcre.org/pcre.txt
Perl Compatible Regular Expressions: http://en.wikipedia.org/wiki/PCRE
PROGRAMS
RegExBuddy: http://www.regexbuddy.com ($40) Screenshot: http://www.regexbuddy.com/screen.html
LIBRARIES
Regular Expression Library: http://regexlib.com/
Categories:
- Uri
- Numbers
- Strings
- Dates and Times
- Misc
- Address/Phone
- Markup/Code
http://www.regular-expressions.info/examples.html
- Grabbing HTML Tags
- Trimming Whitespace
- Matching an IP address
- Matching a Floating Point Number
- Matching an Email Address
- Matching Valid Dates
- Finding or Verifying Credit Card Numbers
- Matching Complete Lines
- Removing Duplicate Lines or Items
- Regex Examples for Processing Source Code
- Two Words Near Each Other
A Collection/Library Of Regular Expressions: http://www.autohotkey.com/forum/viewtopic.php?t=13544
- Ensure that a path doesn't end with a backslash
- Ensure that a path ends with a backslash
- Replace characters illegal in a file name by something else (can be empty)
- Keep only lines starting with a given string
- Parse a date
- trim chars on left and/or right of strings
- How to make parsing loops work from back to front?
- How to replace variable references in a template text file by the value of the referenced variables?
- How to replace i with I only if it has spaces before and after
- remove duplicate lines
N2: Regular Expression EXAMPLES
Examples from: http://www.regular-expressions.info/numericranges.html
Matching Floating Point Numbers with a Regular Expression
Here are a few more common ranges that you may want to match:
000..255: —— ^([01][0-9][0-9]|2[0-4][0-9]|25[0-5])$ 0 or 000..255: —— ^([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])$ 0 or 000..127: —— ^(0?[0-9]?[0-9]|1[0-1][0-9]|12[0-7])$ 0..999: —— ^([0-9]|[1-9][0-9]|[1-9][0-9][0-9])$ 000..999: —— ^[0-9]{3}$ 0 or 000..999: —— ^[0-9]{1,3}$ 1..999: —— ^([1-9]|[1-9][0-9]|[1-9][0-9][0-9])$ 001..999: —— ^(00[1-9]|0[1-9][0-9]|[1-9][0-9][0-9])$ 1 or 001..999: —— ^(0{0,2}[1-9]|0?[1-9][0-9]|[1-9][0-9][0-9])$ 0 or 00..59: —— ^[0-5]?[0-9]$ 0 or 000..366: —— ^(0?[0-9]?[0-9]|[1-2][0-9][0-9]|3[0-6][0-9]|36[0-6])$
Examples from: http://www.codeproject.com/KB/dotnet/regextutorial.aspx
1. elvis Find elvis 2. \belvis\b Find elvis as a whole word 3. \belvis\b.*\balive\b Find text with "elvis" followed by "alive" 4. \b\d\d\d-\d\d\d\d Find seven-digit phone number 5. \b\d{3}-\d{4} Find seven-digit phone number a better way 6. \ba\w*\b Find words that start with the letter a 7. \d+ Find repeated strings of digits 8. \b\w{6}\b Find six letter words 9. .^\d{3}-\d{4}$ Validate a seven-digit phone number 10. \b\w{5,6}\b Find all five and six letter words 11. \b\d{3}\s\d{3}-\d{4} Find ten digit phone numbers 12. \d{3}-\d{2}-\d{4} Social security number 13. ^\w* The first word in the line or in the text 14. \(?\d{3}[) ]\s?\d{3}[- ]\d{4} A ten digit phone number 15. \S+ All strings that do not contain whitespace characters 16. \b\d{5}-\d{4}\b|\b\d{5}\b Five and nine digit Zip Codes 17. (\(\d{3}\)|\d{3})\s?\d{3}[- ]\d{4} Ten digit phone numbers, a better way. This expression will find phone numbers in several formats, like "(800) 325-3535" or "650 555 1212". The "\(?" searches for zero or one left parentheses, "[) ]" searches for a right parenthesis or a space. The "\s?" searches for zero or one whitespace characters. Unfortunately, it will also find cases like "650) 555-1212" in which the parenthesis is not balanced. Below, you'll see how to use alternatives to eliminate this problem. 18. (\d{1,3}\.){3}\d{1,3} A simple IP address finder 19. ((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?) IP finder 20. \b(\w+)\b\s*\1\b Find repeated words 21. \b(?<Word>\w+)\b\s*\k<Word>\b Capture repeated word in a named group 22. \b\w+(?=ing\b) The beginning of words ending with "ing" 23. (?<=\bre)\w+\b The end of words starting with "re" 24. (?<=\d)\d{3}\b Three digits at the end of a word, preceded by a digit 25. (?<=\s)\w+(?=\s) Alphanumeric strings bounded by whitespace 26. \b\w*q[^u]\w*\b Words with "q" followed by NOT "u" 27. \b\w*q(?!u)\w*\b Search for words with "q" not followed by "u" 28. \d{3}(?!\d) Three digits not followed by another digit 29. (?<![a-z ])\w{7} Strings of 7 alphanumerics not preceded by a letter or space 30. (?<=<(\w+)>).*(?=<\/\1>) Text between HTML tags 31. Text between HTML tags (see referenced source page above) 32. a.*b The longest string starting with a and ending with b 33. a.*?b The shortest string starting with a and ending with b
Phone numbers:
a. \(\d\d\d\)\s\d\d\d-\d\d\d\d b. \(\d{3}\)\s\d{3}-\d{4} 4. \b\d\d\d-\d\d\d\d Find seven-digit phone number 5. \b\d{3}-\d{4} Find seven-digit phone number a better way 9. .^\d{3}-\d{4}$ Validate a seven-digit phone number 11. \b\d{3}\s\d{3}-\d{4} Find ten digit phone numbers 14. \(?\d{3}[) ]\s?\d{3}[- ]\d{4} A ten digit phone number 17. (\(\d{3}\)|\d{3})\s?\d{3}[- ]\d{4} Ten digit phone numbers, a better way.
Dates:
a. (\d\d)-(\d\d)-(\d\d\d\d) MM-DD-YYYY (MM -& $1, DD -& $2, YYY -& $3) b. (\d\d\d\d)-(\d\d)-(\d\d) YYYY-MM-DD (YYYY -& $1, MM -& $2, DD -& $3) c. ^\d{1,2}\/\d{1,2}\/\d{4}$ XX/XX/YYYY where XX can be 1 or 2 digits long and YYYY is always 4 digits long.
/******************************************************************************
N3: RegExReplace
N3.1: Basic examples
; Examples f1 := RegExReplace("55555", "5", "five") ;f1 = "fivefivefivefivefive" MsgBox f1=%f1% f2 := RegExReplace("55555", "55", "x") ;f2 = "xx5" MsgBox f2=%f2%
N3.2: EXTRACT Month, Day, Year, from 1/22/2009
;Regular Expression to EXTRACT Month, Day, Year, from 1/22/2009 ;month & day can be 1 or 2 digits c := "xxxxxxxx 1/22/2009 yyyyyyyyyyyy" month := RegExReplace(c,".*?(\d{1,2})\/(\d{1,2})\/(\d{4})(.*)","$1") day := RegExReplace(c,".*?(\d{1,2})\/(\d{1,2})\/(\d{4})(.*)","$2") year := RegExReplace(c,".*?(\d{1,2})\/(\d{1,2})\/(\d{4})(.*)","$3") MsgBox month=%month%`nday=%day%`nyear=%year%
N3.3: An example of how we can step by step build up our Regular Expression
;An example of how we can step by step build up our Regular Expression ;Given string c, extract the data... c := " 02-17-2009 238 Payment by Check. 314.15 9,265.35 " ;Trim leading and trailing spaces c = %c% ; 1. ; c := "02-17-2009 238 Payment by Check. 314.15 9,265.35" ; Start with "(.*)" which grabs the whole string f3 := RegExReplace(c, "(.*)", "$1") MsgBox f3=%f3% ; f3 = "02-17-2009 238 Payment by Check. 314.15 9,265.35" ; 2. ; c := "02-17-2009 238 Payment by Check. 314.15 9,265.35" ; Add "(\d\d)" to parse off the first two digits (the month) f4 := RegExReplace(c, "(\d\d)(.*)", "{$1} {$2}") MsgBox f4=%f4% ; f4 = "{02} {-17-2009 238 Payment by Check. 314.15 9,265.35}" ; 3. ; c := "02-17-2009 238 Payment by Check. 314.15 9,265.35" ; Add "-" to parse off the dash f5 := RegExReplace(c, "(\d\d)-(.*)", "{$1} {$2}") MsgBox f5=%f5% ; f5 = "{02} {17-2009 238 Payment by Check. 314.15 9,265.35}" ; 4. ; c := "02-17-2009 238 Payment by Check. 314.15 9,265.35" ; Add "(\d\d)" to parse off the second two digits (the day) and save it as $2 f6 := RegExReplace(c, "(\d\d)-(\d\d)(.*)", "{$1} {$2} {$3}") MsgBox f6=%f6% ; f6 = "{02} {17} {-2009 238 Payment by Check. 314.15 9,265.35}" ; 5. ; c := "02-17-2009 238 Payment by Check. 314.15 9,265.35" ; Add "-" to parse off the dash f6 := RegExReplace(c, "(\d\d)-(\d\d)(.*)", "{$1} {$2} {$3}") MsgBox f6=%f6% ; f6 = "{02} {17} {-2009 238 Payment by Check. 314.15 9,265.35}" ; 6. ; c := "02-17-2009 238 Payment by Check. 314.15 9,265.35" ; Add "(\d\d\d\d)" to parse off the year (4 digits) and save it as $3 f7 := RegExReplace(c, "(\d\d)-(\d\d)-(\d\d\d\d)(.*)", "{$1} {$2} {$3} {$4}") MsgBox f7=%f7% ; f7 = "{02} {17} {2009} { 238 Payment by Check. 314.15 9,265.35}" ; 7. ; c := "02-17-2009 238 Payment by Check. 314.15 9,265.35" ; Add " +" to parse off one or more spaces f8 := RegExReplace(c, "(\d\d)-(\d\d)-(\d\d\d\d) +(.*)", "{$1} {$2} {$3} {$4}") MsgBox f8=%f8% ; f8 = "{02} {17} {2009} {238 Payment by Check. 314.15 9,265.35}" ; 8. ; c := "02-17-2009 238 Payment by Check. 314.15 9,265.35" ; Add "(\d+)" to parse off the check number (one or more digits) and save it as $4 f9 := RegExReplace(c, "(\d\d)-(\d\d)-(\d\d\d\d) +(\d+)(.*)", "{$1} {$2} {$3} {$4} {$5}") MsgBox f9=%f9% ; f9 = "{02} {17} {2009} {238} { Payment by Check. 314.15 9,265.35}" ; 9. ; c := "02-17-2009 238 Payment by Check. 314.15 9,265.35" ; Add " +" to parse off one or more spaces f10 := RegExReplace(c, "(\d\d)-(\d\d)-(\d\d\d\d) +(\d+) +(.*)", "{$1} {$2} {$3} {$4} {$5}") MsgBox f10=%f10% ;f10 = "{02} {17} {2009} {238} {Payment by Check. 314.15 9,265.35}" ; 10. ; c := "02-17-2009 238 Payment by Check. 314.15 9,265.35" ; Add "(.*?)" to parse off the text (minimal match), followed by " {5}" to parse off 5 spaces ; (there apparently is always 5 spaces. This tells us when we're done parsing off the text.) f11 := RegExReplace(c, "(\d\d)-(\d\d)-(\d\d\d\d) +(\d+) +(.*?) {5}(.*)", "{$1} {$2} {$3} {$4} {$5} {$6}") MsgBox f11=%f11% ; f11 = "{02} {17} {2009} {238} {Payment by Check.} {314.15 9,265.35}" ; 11. ; c := "02-17-2009 238 Payment by Check. 314.15 9,265.35" ; Add "([\d,.]+)" to parse off the dollars and cents (one or more digits with possible commas and decimal point, e.g. 27,182.81) f12 := RegExReplace(c, "(\d\d)-(\d\d)-(\d\d\d\d) +(\d+) +(.*?) {5}([\d,.]+)(.*)", "{$1} {$2} {$3} {$4} {$5} {$6} {$7}") MsgBox f12=%f12% ; f12 = "{02} {17} {2009} {238} {Payment by Check.} {314.15} { 9,265.35}" ; 12. ; c := "02-17-2009 238 Payment by Check. 314.15 9,265.35" ; Add " {3}" to parse off 3 spaces (apparently always 3) f13 := RegExReplace(c, "(\d\d)-(\d\d)-(\d\d\d\d) +(\d+) +(.*?) {5}([\d,.]+) {3}(.*)", "{$1} {$2} {$3} {$4} {$5} {$6} {$7}") MsgBox f13=%f13% ;f13 = "{02} {17} {2009} {238} {Payment by Check.} {314.15} {9,265.35}" ; 13. ; c := "02-17-2009 238 Payment by Check. 314.15 9,265.35" ; Add "([\d,.]+" to parse off the dollars and cents (one or more digits with possible commas and decimal point, e.g. 27,182.81) f14 := RegExReplace(c, "(\d\d)-(\d\d)-(\d\d\d\d) +(\d+) +(.*?) {5}([\d,.]+) {3}([\d,.]+)(.*)", "{$1} {$2} {$3} {$4} {$5} {$6} {$7} {$8}") MsgBox f14=%f14% ; f14 = "{02} {17} {2009} {238} {Payment by Check.} {314.15} {9,265.35} {}" ; (the last empty {} indicates there's nothing left over)
N3.4: Find the $ dollar sign. Extract price and add a $.
;find the $ dollar sign c := "xxx $17.25 yyy" dollar := RegExReplace(c,"(.*?)(\$)(.*)","$2") MsgBox dollar=%dollar% ;extract price and add a dollar sign c := "xxx 17.25 yyy" price := RegExReplace(c,"(.*?)([\d,.]+)(.*)","$$$2") msgbox price=%price% ; price = "$17.25" ; For RegExReplace replace string only: ; To specify a literal $, use $$ ; $ is the only character that needs such special treatment in a RegEx replace string. ; Backslashes are never needed to escape anything else in a RegEx replace string. ; (RegEx search string still needs to have many characters escaped.)
/******************************************************************************
O: Misc AutoHotkey Notes & Debugging Tips
O1: Notes / Caveats
|
ALL VARIABLES ARE STORED AS CHARACTER STRINGS !!! Strings containing numbers are converted to numbers when needed, and the result is converted back to a string. |
|
Closing */ must be first thing on line. Otherwise you'll be asking yourself, "Why does my script stop running at this point, as if the whole rest of the script was commented out?" MsgBox Hello /* here is a comment and another comment */ MsgBox Goodbye ;You'll never see this message MsgBox Hello /* here is a comment and another comment */ MsgBox Goodbye ;Now you're OK |
|
Space here ruins function call ↓ MyFunc (Param1) MyFunc(Param1) |
- When sending text, if there are problems, sometimes it helps to throw in a short delay (Sleep 100), or to slow down the sending of characters by using SetKeyDelay (e.g.SetKeyDelay 90)
- MsgBox: You may need to manually restore focus to your current window after a call to MsgBox. I was debugging an AutoHotkey script by throwing in a bunch of MsgBox messages, and I discovered a problem that focus wasn't being returned to my window after the MsgBox timed out. So, I added a WinActivate after MsgBox to restore focus to my window, and all was well again.
(May have been caused by cross contamination from another unrelated program. I'm so tired of debugging Windows programs only to discover there's nothing wrong with the program I'm debugging, it's the Windows OS itself that's been corrupted by a completely unrelated program. I thought those days were long behind us.)
Update: I had another case where this fix was exactly the wrong thing to do. The "current window" wasn't the one I wanted. Removing the WinExist/WinActivate combo fixed the problem. (Alas, no solution is universal.)
O2: Sending Debug Data To A Log File
;Example 1. Log a message SetWorkingDir, %A_ScriptDir% ;Set default directory to where this script file is located LogFile := "MyLog.txt" FileAppend, This is a message`n, %LogFile% ;(note the trailing (`n) to start a new line. This could instead be a leading (`n) if you want.
;Example 2. Include a time stamp SetWorkingDir, %A_ScriptDir% ;Set default directory to where this script file is located LogFile := "MyLog.txt" FormatTime, TimeString, , yyyy-MM-dd hh:mm:ss tt FileAppend, `n%TimeString% : This is a message`n, %LogFile%
;Example 3. Put it all in a function named LogMsg SetWorkingDir, %A_ScriptDir% ;Set default directory to where this script file is located LogFile := "MyLog.txt" LogMsg("This is a message") ;Note LogMsg adds a leading (`n) so each message starts on a new line LogMsg("Variable X = " . X ) ;Concatenate using the dot . ExitApp ;--------------------------- ;And here is our function: LogMsg( msg ) { global LogFile FormatTime, TimeString, , yyyy-MM-dd hh:mm:ss tt FileAppend, `n%TimeString% : %msg%, %LogFile% }
Update: I've had cases where using FileAppend too frequently causes it to occasionally fail. An expected line in the log file just isn't there. You can check ErrorLevel, but there's no way to get further info on why it failed. Tech note: This may be because FileAppend closes the file every time. That can be a lot of opening/closing a file.
O3: Capturing a screen image during run using IrfanView
/****************************************************************************** Capturing a screen image during run using IrfanView (www.irfanview.com) */ RunWait "C:\Program Files\IrfanView\i_view32.exe" "/capture=1 /convert=C:\TEMP\MyImage.bmp"
/******************************************************************************
P: Misc AutoHotkey Scripts:
P1: Misc AutoHotkey Scripts
- Laptop Low Battery Alert (BatteryDeley): http://www.autohotkey.com/forum/viewtopic.php?t=40683
- Laptop Battery Indicator (PowerCircle): http://powercircle.aldwin.us/
- Laptop Battery Indicator (PowerMeter+): http://mattcollinge.wordpress.com/software/power-meter-plus/
- System Uptime: http://www.autohotkey.com/forum/topic18534.html
- DimScreen: http://www.donationcoder.com/Software/Skrommel/#DimScreen
- Extract Informations about TaskButtons http://www.autohotkey.com/forum/viewtopic.php?t=18652
- Extra mouse button does left click & hold (one line script)
XButton2::click down
P2: Index of notable scripts found in the AutoHotkey Forum : http://www.autohotkey.com/wiki/index.php?title=Script_Listing
|
P3: AHK Functions - ƒ()
http://www.autohotkey.com/forum/viewtopic.php?t=8728
- AUTOHOTKEY:
- VarExist(Var) - http://www.autohotkey.com/forum/viewtopic.php?p=83371#83371
- ƒ() - Pass an array of integers to a function. http://www.autohotkey.com/forum/viewtopic.php?p=242750#242750
- STRINGS:
- SetWidth(Str,Width,AlignText) - increase a string's length by adding spaces to it and aligns it Left/Center/Right.
- NumFormat( Number, Width, Dec, PadChar ) - format a float. Pad leading characters (any character) to a numeric string.
- Replicate(chr,x)
Replicate(chr(196),80) - creates a horizontal ruling 80 characters wide - Space(Width)
Space(80) - 80 spaces - UPPER(String)
- LOWER(String)
- PROPER(String)
- RandStr() - Generates and returns a Random string. http://www.autohotkey.com/forum/viewtopic.php?p=217712#217712
- HashStr() - Hashes a String and returns value as hex.
- Hash() - Hashes a Byte-array and returns value as hex.
- http://www.autohotkey.com/forum/viewtopic.php?p=231784#231784
- Last Day Of Month (e.g. 30, 31, 28, 29) LDOM() - http://www.autohotkey.com/forum/viewtopic.php?p=54502#54502
- YearMonthDay format - http://www.autohotkey.com/forum/viewtopic.php?p=54532#54532
- COLOR:
- HEX2RGB(HEXString,Delimiter="")
- RGB2HEX(RGBString,Delimiter="")
- CheckHexC(HEXString) - validates a "Hex Color Code" by calling the above two functions.
Examples:
HEX2RGB("FFFFFF") -> "255,255,255"
RGB2HEX("255,255,255") -> "FFFFFF"
CheckHexC("FFFFFF") -> 1
CheckHexC("GOYYAH") -> 0
- ChooseColor() - wrapper function for windows ChooseColor Dialog. http://www.autohotkey.com/forum/viewtopic.php?p=103432#103432
- ColorAdjL() - Adjust Luminance for a given RGB color. In other words, this function can derive a lighter / darker shade for a given RGB color.http://www.autohotkey.com/forum/viewtopic.php?p=238242#238242
- GetSysColor() - calls windows GetSysColor function http://www.autohotkey.com/forum/viewtopic.php?p=66521#66521
- windows GetSysColor function: http://msdn.microsoft.com/en-us/library/ms724371.aspx
- FILES:
- GetShortPathName(LongPath)
using %A_LoopFileShortPath% - http://www.autohotkey.com/forum/viewtopic.php?p=69345#69345
using DllCall - http://www.autohotkey.com/forum/viewtopic.php?p=69366#69366 - GetFileFolderSize(fPath) - http://www.autohotkey.com/forum/viewtopic.php?p=82689#82689
- DriveSpace() - Returns the FreeSpace / Capacity of a Drive in bytes. http://www.autohotkey.com/forum/viewtopic.php?p=92483#92483
- ShellFileOperation() - Basic Wrapper. A shell function that can be called to Copy / Move / Delete / Rename File(s).http://www.autohotkey.com/forum/viewtopic.php?p=133249#133249
- GetBinaryType() - Determines whether a file is executable, and if so, what type of executable file it is. http://www.autohotkey.com/forum/viewtopic.php?p=66383#66383
- FileGetVersionInfo() - Extracts and returns version information from an executable file. http://www.autohotkey.com/forum/viewtopic.php?p=233188#233188
- GetShortPathName(LongPath)
- SOUND:
- SoundCard() - Returns the number of soundcards available on a system. http://www.autohotkey.com/forum/viewtopic.php?p=88891#88891
- SoundExC() - SoundEx Classic Version. Phonetic algorithm for indexing names by sound (English). http://www.autohotkey.com/forum/viewtopic.php?p=240065#240065
- IMAGES:
- ConvertGraphicsFile() - Converts image file format between GIF/BMP/JPG/PNG. http://www.autohotkey.com/forum/viewtopic.php?p=190227#190227
- VIDEO:
- AviFileInfo() - Returns the video properties of an AVI file http://www.autohotkey.com/forum/viewtopic.php?p=91036#91036
- SYSTEM:
- GetPriority(ProcessName) - http://www.autohotkey.com/forum/viewtopic.php?p=80548#80548
- ProcessOwner() - Returns the Owner for a given Process ID. http://www.autohotkey.com/forum/viewtopic.php?p=232445#232445
- ProcessCreationTime( ProcessID ) - http://www.autohotkey.com/forum/viewtopic.php?p=97186#97186
- Affinity_Set() - Sets the CPU to be used in Dual/Quad/Multi core processors / Effectively, this function allows you to choose which AHK script uses what processor.http://www.autohotkey.com/forum/viewtopic.php?p=202460#202460
P4: Library for Text File Manipulation : http://www.autohotkey.net/~heresy/Functions/TXT.ahk
- Basic Functions
- TXT_TotalLines
- TXT_ReadLines
- TXT_Tail
- Alignment Functions
- TXT_AlignLeft
- TXT_AlignCenter
- TXT_AlignRight
- TXT_ReverseLines
- Removement Functions
- TXT_RemoveLines
- TXT_RemoveBlankLines
- TXT_RemoveDuplicateLines
- Replacement Functions
- TXT_Replace
- TXT_RegExReplace
- TXT_ReplaceLine
- Insertion Functions
- TXT_LineNumber
- TXT_InsertLine
- TXT_InsertPrefix
- TXT_InsertSuffix
- Column Functions
- TXT_ColGet
- TXT_ColPut
- TXT_ColCut
- Trimming Functions
- TXT_TrimLeft
- TXT_TrimRight
- CSV Functions
- TXT_GetCSV
- TXT_SetCSV
- File Join/Split Functions
- TXT_ConCat
P5: Tray Icons : http://www.autohotkey.com/wiki/index.php?title=Script_Listing
- Master TrayIcon to control all running instances of AutoHotkey http://www.autohotkey.com/forum/viewtopic.php?p=142958#142958
- Extract Informations about TrayIcons http://www.autohotkey.com/forum/viewtopic.php?t=17314
P6: Force Exit another AutoHotkey script
To force Exit another AutoHotkey script (and have it's icon removed from the system tray):
WM_COMMAND = 0x111 ID_FILE_EXIT = 65405 PostMessage, WM_COMMAND, ID_FILE_EXIT, 0, , <window-title>
Example: To end the DimScreen program (an AutoHotkey script at http://www.donationcoder.com/Software/Skrommel/#DimScreen)
WM_COMMAND = 0x111 ID_FILE_EXIT = 65405 PostMessage, WM_COMMAND, ID_FILE_EXIT, 0, , DimScreen Screen
Notes: The above only works for AutoHotkey scrips (*.ahk, or compiled to *.exe)
To determine the Window Title, run Process Explorer
AutoHotkey has the following WM_COMMAND numbers defined in resource.h
ID_FILE_PAUSE | 65403 |
ID_FILE_SUSPEND | 65404 |
ID_FILE_EXIT | 65405 |
(0x111 is WM_COMMAND) |
Tech note: Other WM_COMMAND numbers defined in AutoHotkey source file resource.h (I haven't tried any of these to see what they do)
ID_FILE_RELOADSCRIPT | 65400 |
ID_FILE_EDITSCRIPT | 65401 |
ID_FILE_WINDOWSPY | 65402 |
ID_FILE_PAUSE | 65403 |
ID_FILE_SUSPEND | 65404 |
ID_FILE_EXIT | 65405 |
ID_VIEW_LINES | 65406 |
ID_VIEW_VARIABLES | 65407 |
ID_VIEW_HOTKEYS | 65408 |
ID_VIEW_KEYHISTORY | 65409 |
ID_VIEW_REFRESH | 65410 |
ID_HELP_USERMANUAL | 65411 |
ID_HELP_WEBSITE | 65412 |
Another way to identify the AutoHotkey script you want to Exit(/Suspend/Pause):
WM_COMMAND = 0x111 ID_FILE_EXIT = 65405 DetectHiddenWindows, On WinGet, AList, List, ahk_class AutoHotkey ; Make a list of all running AutoHotkey programs Loop %AList% { ; Loop through the list ID := AList%A_Index% WinGetTitle, ATitle, ahk_id %ID% ; (You'll notice this isn't the same 'window title') MsgBox, 3, %A_ScriptName%, %ATitle%`n`nEnd? IfMsgBox Cancel Break IfMsgBox Yes PostMessage,WM_COMMAND,ID_FILE_EXIT,0,,% "ahk_id" AList%A_Index% ; End the process (65404 to suspend, 65403 to pause) } ExitApp
/******************************************************************************
Q: NAVIGATING WEB SITES
See example file WebsiteNav.ahk
Q1: DETERMINING WHEN A WEBPAGE HAS FINISHED LOADING
See FAQ: http://www.autohotkey.com/docs/FAQ.htm#load
- Method 1: Wait for status line to say "Done"
See example in file WebsiteNav.ahk
- Method 2: call IEReady()
[Only works for Internet Explorer (afik)]
See post "Determine if a WebPage is completely loaded in IE" : http://www.autohotkey.com/forum/topic19256.html
See example in file WebsiteNav.ahk- Download Com.zip from: http://www.autohotkey.net/~Sean/Lib/COM.zip
(See "COM Standard Library" post: http://www.autohotkey.com/forum/topic22923.html)
Unzip and place COM.ahk here: C:\Program Files\AutoHotkey\Lib\COM.ahk - Download function IEReady from: http://www.autohotkey.com/forum/topic19256.html
Add fuction IEReady to your .ahk code - Place a call to IEReady() in your .ahk code when you want to wait until the page is loaded.
- Download Com.zip from: http://www.autohotkey.net/~Sean/Lib/COM.zip
- Method 3: See "Detect when a page is loaded (reliable, cross-browser)" post: http://www.autohotkey.com/forum/topic35056.html
- Methods 4,5,6,...
For more advanced methods see these two posts:
("This is left as an exercise for the student", which is what the professor says when it's over his head.)- Automation IE7 Navigation and Scripting with Tabs
http://www.autohotkey.com/forum/viewtopic.php?t=30599 - IE and Gui Browser Com Tutorial
http://www.autohotkey.com/forum/viewtopic.php?t=34972
- Automation IE7 Navigation and Scripting with Tabs
Q2: POSITION US ON A CERTAIN CONTROL
Examples are from simple to more complex. All examples here are demonstrated in file WebsiteNav.ahk
- Method 1: Blindly hit the {Tab} key a certain number of times to position us where we want to be.
(Not very reliable. e.g. User may have Google toolbar installed, which we'd have to tab through.
Or perhaps Yahoo toolbar. Or no toolbar. Who knows...)
Example:Send {Tab 34} ;say, 34 tabs gets us where we want to be.
- Method 2. Hit the {Tab} key until certain text appears in the status bar
For this example, assume we are at http://www.autohotkey.com/ and we wish to position ourselves on the Wiki link:; For this example, Tab until we find the autoHotkey "Wiki" link ; When we tab to the AutoHotkey "Wiki" link, the status bar says "http://www.autohotkey.com/wiki/" target := "http://www.autohotkey.com/wiki/" loop, 40 { sleep 10 ;this pause may help StatusBarGetText, StatBar, , AutoHotkey - Free Mouse and Keyboard Macro Program if (StatBar = target) { goto FOUNDIT } Send, {Tab} } ;If we drop out here, it means we failed to find our target after 40 tabs MsgBox Failed to find %target% ExitApp FOUNDIT: MsgBox Found target %target%
- Method 2.5 Hit Shift+Tab to tab backwards until certain text appears in the status bar
(May be useful if tabbing forwards doesn't work)
- Method 3. Search for word which is link you want to click on
- Method 4. Jump directly to the control
The JavaScript method—we place some JavaScript code in the address bar and execute it to jump directly to the control. This is a faster and more reliable technique, but it's a bit more complicated to set up. We use AutoHotkey ControlSetText to place the JavaScript code in the address bar, specifying the HTML control ID, or the control NAME, of the control we want to jump to, then we use AutoHotkey ControlSend to execute that JavaScript.
For this example, assume we are at http://www.autohotkey.com/wiki/ and we wish to position ourselves in the Search field.
Determine the ID or NAME of the control:- Method 1: Read and decypher the HTML source code. Look for " ID="
e.g. for page http://www.autohotkey.com/wiki/
we find this line of code:<INPUT id=searchInput title="Search AutoHotkey [f]" accessKey=f name=search> ^^^^^^^^^^^ ^^^^^^
Here our ID is searchInput, and our NAME is search (we only need one. Either ID or NAME. The ID is best if it's available.)
- Method 2: Use a tool to help us find the ID or NAME
- Use the Microsoft "Internet Explorer Developer Toolbar" for Internet Explorer 7.
(Note: for Internet Explorer 8, see "Discovering Internet Explorer Developer Tools" at http://msdn.microsoft.com/en-us/library/cc848894(VS.85).aspx )- Download and install : http://www.microsoft.com/downloads/details.aspx?familyid=E59C3964-672D-4511-BB3E-2D5E1DB91038&displaylang=en
- Navigate to your webpage (using Internet Explorer 7)
- Bring up the "IE Developer Toolbar". (Note: If you do not see the "IE Developer Toolbar" button on the toolbar, it may be off to the right. Click the right-facing arrows at the end of the IE7 command bar to view all available toolbar buttons.)
- FIND -> SELECT ELEMENT BY CLICK
- Move your mouse to the desired element and click.
- In the middle pane ('Attribute:') scroll down and find the ID string.
If there is no ID string, find the NAME string.
If there is no NAME string, cripes, it gets a bit difficult. You'll
have to read up on Javascript and the DOM (Document Object Model).
- Use Firefox and install the Firebug add-on at http://getfirebug.com/
- There are other similar programs to help you examine the source code for web pages. Here are a few:
- PageSpy — http://www.sembel.net
- Debugbar — http://www.debugbar.com
- Use the Microsoft "Internet Explorer Developer Toolbar" for Internet Explorer 7.
For these examples assume you're at http://www.autohotkey.com/wiki/- General format using ID:
; Position to a Control Using the Control's Unique ID ControlSetText, Edit1, javascript:document.getElementById('<element-ID>')[0].focus() ControlSend, Edit1, {Enter}, <window-title> Sleep 100 ;give it a moment too do it's thing (important)
(Caution: getElementById is case sensitive! I originally tried getElementByID (last letter D instead of d) and it didn't work.)
Example using ID:; Position to a Control Using the Control's Unique ID ; For this example the control's ID is searchInput ; and the window title contains the word AutoHotkey ControlSetText, Edit1, javascript:document.getElementById('searchInput').focus() ControlSend, Edit1, {Enter}, AutoHotkey Sleep 100 ;give it a moment too do it's thing (important)
- General format using NAME:
; Position to a Control Using the Control's NAME ControlSetText, Edit1, javascript:document.getElementsByName('<element-name>')[0].focus() ControlSend, Edit1, {Enter}, <window-title> Sleep 100 ;give it a moment too do it's thing (important)
Example using NAME:; Position to a Control Using the Control's NAME ; For this example the control's NAME is search ; and the window title contains the word AutoHotkey ControlSetText, Edit1, javascript:document.getElementsByName('search')[0].focus() ControlSend, Edit1, {Enter}, AutoHotkey Sleep 100 ;give it a moment too do it's thing (important)
If more than one control has the same name:- Go kick George Foreman in the shin for naming all 5 of his sons "George" (and two of his daughters).
- Then figure out what number to use instead of [0] to get to the n'th control with that NAME.
(Note: There is no legal way to use the NAME attribute from such tags as DIV or SPAN, according to the W3C HTML 4.01 specs. You must confine the usage of this attribute to such tags as INPUT, IMG, FRAME, IFRAME, FORM, MAP, PARAM, META, OBJECT, A, SELECT, APPLET, TEXTAREA, or BUTTON. (Those who use XML or XHTML or XFILES or whatever may have different rules to play by.)
If the control you want has no ID or NAME:- Argh! This is getting hard! You'll have to go read up about JavaScript and the DOM (Document Object Model)
Some things you could try:
javascript:document.getElementsByTagName('a')[6].focus() ; Get the 7th <A> tag in the document (numbering begins with 0). javascript:document.links[6].focus() ; Get the 7th link in the document (numbering begins with 0).
- Method 1: Read and decypher the HTML source code. Look for " ID="
- Methods 5,6,7,...
For more advanced methods see these two posts:- Automation IE7 Navigation and Scripting with Tabs
http://www.autohotkey.com/forum/viewtopic.php?t=30599 - IE and Gui Browser Com Tutorial
http://www.autohotkey.com/forum/viewtopic.php?t=34972
("This is left as an exercise for the student", which again is what the professor says when it's over his head.)
- Automation IE7 Navigation and Scripting with Tabs
Q3: SEARCH FOR A COLORED PIXEL
Note: If I'm searching a white background for black text, I find it works better to search for "not white" rather than search for "black", because sometimes that black text isn't really black when you look at it closely.
The following actually goes quite fast if you comment out the moving of the mouse. I move the mouse here for demonstration purposes.
WinGetPos, winposX, winposY, Width, Height, A ;Get window Width, Height ;MsgBox, 0, , winposX=%winposX%`n winposY=%winposY% `nWidth=%Width% `nHeight=%Height%, ;Calculate a starting position X := Width - 60 Y := Height / 2 MouseMove, X, Y, 7 MsgBox, 0, , Move left until we find "not white", 1.2 ;move left until we find "not white" loop 200 { MouseMove, X, Y, 0 PixelGetColor, color, X, Y, RGB ;MsgBox, 0, , color=%color%, 0.1 if (color <> "0xFFFFFF") { Goto FOUND_TCOLOR } X -= 1 } ;If we drop out here, it means we failed to find our target MsgBox, 0, , Failed to find color "not white", 2 goto Exit FOUND_TCOLOR: MsgBox, 0, , Found "not white". color = %color%, 2 Exit: MsgBox, 0, , The End, 2 ExitApp
/************************************************
R: NEWBIE RECOMMENDED LEARNING SEQUENCE
Reference: Recommended by jaco0646 (thank you jaco0646)
http://www.autohotkey.com/forum/viewtopic.php?t=29204)
- Commands dealing with files start with FILE
- Commands dealing with windows start with WIN
- Commands dealing with text start with STRING
Similarly:
- Commands that retrieve data from somewhere contain GET
- Commands that apply data to somewhere contain SET
Suggested order of study for AutoHotkey newbies:
First:
- read the Tutorial
- the Scripts page
- the FAQ
Afterwards, recommend learning concepts in the following order:
- Hotstrings
- Hotkeys
- Mouse Clicks & Mouse HotKeys
- Variables
- Loops - especially Parsing Loops
- String commands - (e.g. StringMid, StringReplace)
- If,Else statements
- Expressions
- Arrays & Dynamic variables - (StringSplit)
- GoSub & Functions
- GUIs
- Windows Messages
- DllCall
/******************************************************************************
S: PRESS ESC TO CANCEL THIS SCRIPT
Defining Hotkeys
A hotkey definition line stops execution at that point, so if you want the
script to run to the end but have the ESC key available to terminate the script,
put the hotkey definition at the end, just after your ExitApp statement.
;Press ESC to cancel this script Esc::ExitApp
/******************************************************************************
T: THE AUTOHOTKEY RUN COMMAND
Program:
Run, ShowParams.exe hello goodbye Friday
AutoHotkey script:
Run, autohotkey.exe ShowParams.ahk hello goodbye Friday
VBScript:
Run, cscript.exe ShowParams.vbs hello goodbye Friday
JScript:
Run, cscript.exe ShowParams.js hello goodbye Friday
Any command:
┌───── cmd.exe strips off these outer " ───────┐ Run, "%comspec%" /c ""ShowParams.ahk" "hello" "goodbye" "friday"", , Hide
Hide is specified to prevent the Command Prompt Window from popping up.
/c causes Command Prompt Window to exit after command is executed.
/k instead of /c would cause Command Prompt Window to remain open after command is executed. Useful for debugging.
Notes:
AutoHotkey scripts:
Why does specifying just 'autohotkey.exe' work? Because the AutoHotkey installer adds the following entry to the registry:
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\AutoHotkey.exe]
@="C:\\Program Files\\AutoHotkey\\AutoHotkey.exe"
VBscript and JScript:
You may also use wscript.exe — wscript.exe is the windows version, cscript.exe is the console version. You'll find them in the System32 directory.
(JScript is Microsoft's own version of JavaScript.)
The comspec environment variable usually equates to C:\Windows\System\System32\cmd.exe . On Windows 95,98,ME it equates to COMMAND.COM . It's also possible the user may have changed it to run a fancier command prompt such as JPSoft's Take Command command line utility (http://jpsoft.com)
The AutoHotkey RUN command currently does not parse <target> the way you'd expect it to, so the results often aren't quite what you wanted. Here's how it works:
- Autohotkey parses off the <target> parameter.
The <target> parameter is delimited by a comma, so if you want to include a comma somewhere in the target parameter, you need to escape it with a ` - Autohotkey expands any variables (e.g. %day%).
Variables are delimited by %, so if you want to include a literal % somewhere in the <target> parameter, you need to escape it with a ` - AutoHotkey tries calling CreateProcess() passing the processed <target> parameter as the lpCommandLine argument.
- If CreateProcess() fails, AutoHotkey tries calling ShellExecute() passing the processed <target> parameter as the lpFile parameter. Note: This is where it would be nice if AutoHotkey would split <target> between the command and parameters, passing the command as lpFile and the parameters as lpParameters, but it doesn't. It instead passes the entire line as the lpFile parameter, leaving the lpParameters argument NULL. The reason for this is the design decision mentioned in the AutoHotkey source code file script.cpp routine ActionExec: "User can launch a document name containing spaces without having to enclose it in double quotes."
An alternative to using Run is to directly call ShellExecute() :
command = ShowParams.ahk params = hello goodbye Friday res := DllCall("shell32\ShellExecuteA" , "UInt", 0 ; hwnd , "UInt", 0 ; lpOperation , "Str", command ; lpFile , "Str", params ; lpParameters , "Str", A_WorkingDir ; lpDirectory , "UInt", 0) ; nShowCmd MsgBox (%ErrorLevel%) %res%
/******************************************************************************
U: PASSING PARAMETERS TO AUTOHOTKEY SCRIPTS
On Windows, parameters are parsed off the command line after the new process is created, by the new process. It's considered the responsibility of the newly started application to call theGetCommandLine() API to retrieve the command line string and parse it.
How does a C/C++ program on Windows get argv[]? The C/C++ compiler which compiles the program secretly adds extra code to the executable that retrieves and parses the command line to extract the parameters before calling WinMain (or main). Thus, for a C/C++ executable on Windows, the parameter parsing rules are determined by the C/C++ compiler that compiled the program.
AutoHotkey is written in C++ and obtains its parameters via the argv[] vector.1 Thus it uses the Microsoft C/C++ Parameter Parsing Rules. The rules are:
- Parameters are always separated by a space or tab (multiple spaces/tabs OK)
- If the parameter does not contain any spaces, tabs, or double quotes, then all the characters in the parameter are accepted as is (there is no need to enclose the parameter in double quotes).
- Enclose spaces and tabs in a double quoted part
- A double quoted part can be anywhere within a parameter
- 2n backslashes followed by a " produce n backslashes and start or end a double quoted part
- 2n+1 backslashes followed by a " produce n backslashes + a literal quotation mark
- n backslashes not followed by a quotation mark produce n backslashes
- If a closing " is followed immediately by another ", the 2nd " is accepted literally and added to the parameter (this is the undocumented rule)
For more on passing parameters to programs, with numerous examples, see the essay How Command Line Parameters Are Parsed
Notes:
1. Actually AutoHotkey uses the __argv[] vector.
/******************************************************************************
V: PASSING PARAMETERS TO ANY PROGRAM
You aren't sure how to escape the special characters in that parameter so it comes out right? See the essay How Command Line Parameters Are Parsed
/******************************************************************************
My title: "" %% (), And All That, is taken from the wonderful book, Div, Grad, Curl, And All That: An Informal Text on Vector Calculus by H. M. Schey (1973)
History:
Version 1.00 02/28/2009
Version 1.04 03/08/2009
Version 1.05 03/09/2009
Version 1.09 03/26/2009
Version 1.10 04/30/2009
Version 1.12 05/15/2009
Version 1.14 05/24/2009
Version 1.19 06/01/2009
Version 1.21 08/24/2009
Version 1.22 01/02/2011