Alter a specific character of a variable? - autohotkey

Is it possible to target a specific character in a variable in AutoHotkey? In this case I'd like to uppercase/lowercase the first character in the variable.
::foo::
InputBox, foo, Foo, Enter foo:
/*
Capitalize first character of %foo% here.
Do whatever.
*/
return

In your case, StringUpper will do:
stringUpper, foo, foo, T
T stands for:
the string will be converted to title case. For example, "GONE with the WIND" would become "Gone With The Wind". "
Other than that, you can always determine substrings using either StringTrimRight/Left or SubStr(), alter them and append them afterwards:
firstLetter := subStr(foo, 1, 1)
stringUpper, firstLetter, firstLetter
remainingLetters := subStr(foo, 2, strLen(foo))
foo := firstLetter . remainingLetters
; or, equally:
; foo = %firstLetter%%remainingLetters%

Alternative one liner to #Blauhirn's solution:
MsgBox % foo := Format("{:U}", SubStr(foo, 1,1)) . subStr(foo, 2, strLen(foo))
This can also be done in RegEx fairly simply.
::::::Edited::::::::::
Here's a full Example of it's use with the concatenate removed...
fu := "fu"
bar := "beyond all recognition!"
MsgBox % capitalize(fu) A_space capitalize(bar)
Return
capitalize(x) {
return Format("{:U}", SubStr(x, 1,1)) subStr(x, 2, strLen(x))
}
Regular Expression:
;This is the only example that accounts for Whitespace
var := " regex is cool!"
MsgBox % RegExReplace(var, "^(\s*)(.)", "$1$u2")
NumPut/DllCall:
var := "autohotkey is awesome!"
NumPut(Asc(DllCall("CharUpperA", Str,Chr(NumGet( var,0,"UChar")),Str)), var,0,"UChar")
MsgBox % var

Related

Why is the key of my Associative Array a reference to a string and not the string itself?

I have the following string that contains product barcodes:
4016241030924;4016241030924;8710624237479;5900951254741;8710398162939;8710398162939;8710398162939;8710398162939;8710398162939;8710398162939;8710398162939;8710398162939;8710624296933;8710624296872;8710624223885;8710624223885;8711000341001;8711000341001;8711000341001;8710624260415;8710624260415;8710624260415;8710624260415;8710624260415;8710624260415;8710624260415;8710624260415;8710624260415;8710624260453;
What I want to do is:
Split the string by ;
Create an Associative Array where the key is the barcode and the value is the count of the barcode
Loop through the Associative Array and print the key (= barcode) and the value (= count)
Here's what I am trying:
BarcodesAssArray := Array()
BarcodeArray := StrSplit(fileContent, ";")
Loop % BarcodeArray.MaxIndex() - 1 {
thisBarcode := BarcodeArray[a_index]
; Check if barcode already exists
if (BarcodesAssArray[thisBarcode]) {
BarcodesAssArray[thisBarcode] := BarcodesAssArray[thisBarcode] + 1
} else {
BarcodesAssArray[thisBarcode] := 1
}
}
For key, value in BarcodesAssArray
MsgBox, %key% = %value%
But instead of the key being the barcode it is some sort of reference to the barcode. This is what I get:
-333809963 = 1
204486651 = 8
430547597 = 2
430561191 = 1
430584127 = 9
43084165 = 1
...
What I expect to get is:
4016241030924 = 2
8710624237479 = 1
8710398162939 = 8
...
What should I do differently?
Try to simplify the code and take it one step at time
BarcodesAssArray := 4016241030924;4016241030924;8710624237479;5900951254741;8710398162939
BarcodeArray := StrSplit(BarcodesAssArray, ";")
MsgBox BarcodeArray(1) BarcodeArray(2) BarcodeArray(3) BarcodeArray(4) BarcodeArray(5)
This will at least get you past the StrSplit statement knowing that you have a valid array
I haven't coded in a while so run at your own risk :)
"Your problem is probably occurring because the keys in your arrays are being treated as numeric. There are limits on the size of numeric keys, depending on whether you are using 32 bit AutoHotkey or 64 bit. The way I would fix this is to cause the keys to be treated as alpha by appending a constant alpha value to the key in the array and stripping it off when displaying, etc the key. This also deals with the case where leading zeros would otherwise be stripped from the numeric keys."
TAC109 - https://www.autohotkey.com/boards/viewtopic.php?p=312566#p312566
BarcodesString := "4016241030924;4016241030924;8710624237479;5900951254741;8710398162939;8710398162939;8710398162939;8710398162939;8710398162939;8710398162939;8710398162939;8710398162939;8710624296933;8710624296872;8710624223885;8710624223885;8711000341001;8711000341001;8711000341001;8710624260415;8710624260415;8710624260415;8710624260415;8710624260415;8710624260415;8710624260415;8710624260415;8710624260415;8710624260453;"
BarcodesString := RTrim(BarcodesString,";") ; remove trailing ;
BarcodesAssArray := {}
Loop, Parse, BarcodesString, `;
switch BarcodesAssArray.HasKey(A_LoopField . "")
{
case true:BarcodesAssArray[A_LoopField . ""] += 1
case false:BarcodesAssArray[A_LoopField . ""] := 1
}
For key, value in BarcodesAssArray
MsgBox, %key% = %value%
Xtra - https://www.autohotkey.com/boards/viewtopic.php?p=312565#p312565

How to have "input" (or is it context?) dependent hotstrings/hotkeys ?

I want a hotkey or hotstring (whatever is easier), so I can easily convert e.g.
1:5 into [1,2,3,4,5] or
3:7 into [3,4,5,6,7] etc..
I want this to work for all integers...
So I want "multiple variants of the same hotstring" (or, if easier: a hotkey that works somewhat similar: e.g. pressing strg + h and typing 1:3 should produces [1,2,3] )
It should recognize that I typed a number followed by colon followed by another number, and then expand correspondingly..
I looked into the Input function, but it does not seem to be exactly what I want..
I don't need a working solution. Hints & links or keywords for further googling are already helpful..
After typing +h or pressing strg+h, type two numbers to produce the desired outcome:
:*:+h::
^h::
nr := "" ; empty variable's content
end_nr := ""
Input, var, L2 ; Length limit=2
; Input, var, L2 V ; V: Visible
If var is not integer
{
MsgBox, "%var%" is not integer
return
}
first_nr := SubStr(var, 1, 1)
second_nr := SubStr(var, 0)
if (first_nr >= second_nr)
{
MsgBox, "%first_nr%" is greater or equal "%second_nr%"
return
}
Loop
{
nr++ ; increase the number in the variable "nr" by 1 in each iteration
if (nr < first_nr)
continue
If (nr = second_nr)
break
end_nr .= nr . "," ; concatenate the outputs by adding a comma to each one
}
If (first_nr = 0)
MsgBox, "0,%end_nr%%second_nr%"
else
MsgBox, "%end_nr%%second_nr%"
return

Is there a way to assign a multi-line string to a object property?

I know that you can assign a multi-line string to a variable like this:
MyVar =
(
this
is
a
string with multiple
lines
)
But is there a way to assign the above string to an object property? I tried doing it like this but I received an error:
Array := {}
Array["key"] =
(
this
is
a
string with multiple
lines
)
The error says:
The following variable name contains an illegal character
"this
is
a
string"
I just want to be able to open my script in a text editor and copy and paste multiple-line strings directly into the editor as properties of objects.
You have to use the proper assignment operator := with Objects, likewise your text needs be enclosed by Quotes.
Try:
obj := {}
obj["key"] :=
(
"this
is
a
string with multiple
lines"
)
MsgBox % obj["key"]
Or you can do this below:
x =
(
this
is
a
string with multiple
lines
)
obj["key"] := x
MsgBox % obj["key"]
You can also build a multi-line object like so:
obj := {"key":
(
"this
is
a
string with multiple
lines"
)}
MsgBox % obj["key"]
Using a raw multiline string assignment like the following it tends to defeat any indenting you may have cultivated in your script.
str := {"Lines":
(
"first
second
third"
)}
Although that will work. If you're looking to preserve your code indenting then you can create a multiline string by delimiting the lines with `n like this:
str := {"Lines": "first`nSecond`nThird"}

Remove last n characters of string after the dot with Autohotkey

I am using Autohotkey.
I have a string that looks like this S523.WW.E.SIMA. I want to remove the last few characters of the string after the dot (including the dot itself). So, after the removal, the string will look like S523.WW.E.
This may look like a simple question but I just cannot figure out using the available string functions in Autohotkey. How can this be done using Autohotkey? Thank you very much.
Example 1 (last index of)
string := "S523.WW.E.SIMA"
LastDotPos := InStr(string,".",0,0) ; get position of last occurrence of "."
result := SubStr(string,1,LastDotPos-1) ; get substring from start to last dot
MsgBox %result% ; display result
See InStr
See SubStr
Example 2 (StrSplit)
; Split it into the dot-separated parts,
; then join them again excluding the last part
parts := StrSplit(string, ".")
result := ""
Loop % parts.MaxIndex() - 1
{
if(StrLen(result)) {
result .= "."
}
result .= parts[A_Index]
}
Example 3 (RegExMatch)
; Extract everything up until the last dot
RegExMatch(string, "(.*)\.", result)
msgbox % result1
Example 4 (RegExReplace)
; RegExReplace to remove everything, starting with the last dot
result := RegExReplace(string, "\.[^\.]+$", "")

Autohotkey string - Bring segement to front

I would like to bring words with something in front of them to the front.
For example, turn bla bla foobla into foobla bla bla - put the word with foo in the front.
This would be quite easy with another language with stronger string manipulation functions, however I need to use AutoHotKey for functions that it provides.
Right now, I'm thinking of splitting the string into words (split by ' '), but I'm not even sure if I can find out the length of an 'array' in AHK.
Is doing this even possible in AHK?
string := "bla bla fooble"
arr := StrSplit(string, " ")
msgbox % "the number of elements: " arr.maxindex()
removed := arr.remove(arr.maxindex())
arr.insert(1, removed)
For k, v in arr {
output .= k ": " v "`n"
}
msgbox % output
StrSplit(ByRef InputVar, Delimiters="", OmitChars="") {
o := []
Loop, Parse, InputVar, % Delimiters, % OmitChars
o.Insert(A_LoopField)
return o
}