 |
AutoHotkey Community Let's help each other out
|
| View previous topic :: View next topic |
| Author |
Message |
SKAN
Joined: 26 Dec 2005 Posts: 6264
|
Posted: Fri Mar 03, 2006 7:04 am Post subject: StringMod() String Manipulation - Enhanced by PhiLho / Titan |
|
|
StringMod() was originally posted in General Chat topic Numerology .
- PhiLho enhanced the original code & included Replace, Rot13 and Rot47
- Titan re-wrote the function and enhanced it with Scramble, Bloat, Pattern.
Function StringMod() extracts, excludes or replaces specified characters from the String passed on to it and returns
the modified string. It can also flip a string (reversed order) or convert it into Rot13 and Rot47.
Additional functionality are detailed below.
Usage: StringMod(string, method [, param1, param2])
| Quote: |
String Modification: Methods with examples
Methods:
Only
Omit
Flip
Replace
Rot13
Rot47
Scramble
Bloat
Pattern
Examples:
Extract the Vowels from the name "Goyyah"
StringMod("Goyyah","Only","AEIOU") returns "oa"
Extract the Consonants from the name "Goyyah"
StringMod("Goyyah","Omit","AEIOU") returns "Gyyh"
Flips "Goyyah"
StringMod("Goyyah","Flip") returns "hayyoG"
Replace "*^" in "^H*e*l*l*o^" with "_"
StringMod("^H*e*l*l*o^", "Replace" , "*^" , "_") returns "_H_e_l_l_o_"
Example for Validating a String into Filename | Code: | filename = This?Is?\A:/<"Valid"File>*Name?.txt
invalidFilenameCharacters=\/:*?"<>|
Msgbox, % StringMod(filename, "Replace", invalidFilenameCharacters)
; This_Is_A___Valid_File__Name_.txt |
Convert "HELLO" into Rot13
StringMod("Hello", "Rot13") returns "UYRRB"
Convert "HELLO" into Rot47
StringMod("Hello", "Rot47") returns "wt{{~"
Scramble the word "AUTOHOTKEY"
StringMod("AUTOHOTKEY","Scramble") will return something like "UKOTTOEAHY"
- Laszlo's CharPerm() - similar functionality - optimised
Stuff Characters before and after each character in the word "Autohotkey"
StringMod("AutoHotkey","Bloat", "{" , "}" ) returns "{A}{u}{t}{o}{H}{o}{t}{k}{e}{y}"
Pattern may be used to find the Anagrammatical relationship between two words.
Pattern returns a String arranged in alphabetical order in such
a way that the number of occurences follows each letter
Pattern1 := StringMod("RACE","Pattern") ; "A1C1E1R1"
Pattern2 := StringMod("CARE","Pattern") ; "A1C1E1R1"
If Pattern1 = %Pattern2%
; evaluates to a logical true because both Pattern1 and Pattern2 share the same pattern "A1C1E1R1"
|
 _________________

Last edited by SKAN on Mon Jun 16, 2008 1:09 pm; edited 17 times in total |
|
| Back to top |
|
 |
SKAN
Joined: 26 Dec 2005 Posts: 6264
|
Posted: Fri Mar 03, 2006 8:31 am Post subject: |
|
|
Other String Manipulation Functions
StringSlice() : Added 2006-March-19.
| Quote: | StringSlice() : Similar to AHK's StringSplit Command - However, with one difference.
String is Split, based on defined width rather than a delimiter
Example: StringSlice("Dictionary", 3, "Var") will initialise 5 Variables: Var0 through Var4
Var0 will contain 4
Var1 will contain "Dic"
Var2 will contain "tio"
Var3 will contain "nar"
Var4 will contain "y" |
Regards,  _________________

Last edited by SKAN on Sun Mar 19, 2006 12:24 pm; edited 5 times in total |
|
| Back to top |
|
 |
PhiLho
Joined: 27 Dec 2005 Posts: 6721 Location: France (near Paris)
|
Posted: Fri Mar 03, 2006 10:39 am Post subject: |
|
|
Thanks for the credit
For consistency, I would have integrated Flip into the loop:
| Code: | Loop Parse, _string
{
If (_mode = "Flip")
{
rStr := A_LoopField rStr
}
; Is char in the given list?
Else IfInString _chars, %A_LoopField%
{
If (_mode = "Only")
rStr := rStr A_LoopField
Else If (_mode = "Replace")
rStr := rStr _replCh
}
Else
{
If (_mode = "Omit" or _mode = "Replace")
rStr := rStr A_LoopField
}
}
|
Also I believe that the Flip code you gave may give bad results if the string has spaces (in default mode).
Such Flip function is probably not of huge utility, except perhaps to perform some AHK functions that doesn't provide a facility starting from the right of the string. _________________
vPhiLho := RegExReplace("Philippe Lhoste", "^(\w{3})\w*\s+\b(\w{3})\w*$", "$1$2") |
|
| Back to top |
|
 |
PhiLho
Joined: 27 Dec 2005 Posts: 6721 Location: France (near Paris)
|
Posted: Fri Mar 03, 2006 11:21 am Post subject: |
|
|
Another transformation: Rot13, Rot47 and variants.
File can be downloaded from AutoHotkey.net.
| Code: | StringMod(_string, _mode="", _chars="", _replCh="")
{
local rStr, char, ascii, o
; Defaults
If _mode not in Omit,Only,Replace,Flip,Rot13,Rot47
_mode = Omit
If _chars =
{
If _mode = Rot13
_chars = 13
Else If _mode = Rot47
_chars = 47
Else
_chars = %A_Space%
}
If _replCh =
_replCh = _
Loop Parse, _string
{
If (_mode = "Flip")
{
rStr := A_LoopField rStr
}
Else If (_mode = "Rot13")
{
char := Asc(A_LoopField)
; o is 'A' code if it is an uppercase letter, and 'a' code if it is a lowercase letter
o := Asc("A") * (Asc("A") <= char && char <= Asc("Z")) + Asc("a") * (Asc("a") <= char && char <= Asc("z"))
If (o > 0)
{
; Set between 0 and 25, add rotation factor, modulus alphabet size
char := Mod(char - o + _chars, 26)
; Transform back to char, upper or lower
char := Chr(char + o)
}
Else
{
; Non alphabetic, unchanged
char := A_LoopField
}
rStr := rStr char
}
Else If (_mode = "Rot47")
{
char := A_LoopField
If char between ! and ~
{
char := Asc(A_LoopField)
; Set between 0 and 93, add rotation factor, modulus range size
char := Mod(char - 33 + _chars, 94)
; Transform back to char
char := Chr(char + 33)
}
rStr := rStr char
}
; Is char in the given list?
Else IfInString _chars, %A_LoopField%
{
If (_mode = "Only")
rStr := rStr A_LoopField
Else If (_mode = "Replace")
rStr := rStr _replCh
}
Else
{
If (_mode = "Omit" or _mode = "Replace")
rStr := rStr A_LoopField
}
}
Return rStr
}
; Run test code only if the file is ran standalone
If (A_ScriptName = "StringMod.ahk")
{
str = The name of the variable whose contents will be analyzed.
filename = This?Is?\A:/<"Valid"File>*Name?.txt
invalidFilenameCharacters=\/:*?"<>|
r = |
r := r StringMod(str, "OMIT", " ") "|`n|"
r := r StringMod(str, "Omit", "aeiouy") "|`n|"
r := r StringMod(str, "only", " ") "|`n|"
r := r StringMod(str, "Only", "aeiouy ") "|`n"
r := r StringMod(str, "RePlAcE", " ") "|`n|"
r := r StringMod(str, "Replace", "aeiouy", "$") "|`n|"
r := r StringMod(str, "Flip") "|`n|"
r := r StringMod(str, "Rot13") "|`n|"
r := r StringMod(str, "Rot13", 11) "|`n|"
r := r StringMod(str, "Rot47") "|`n|"
r := r StringMod(str, "Rot47", 33) "|`n|"
r := r StringMod(filename, "Omit", invalidFilenameCharacters) "|`n|"
r := r StringMod(filename, "Replace", invalidFilenameCharacters) "|`n|"
r := r StringMod(filename, "Replace", invalidFilenameCharacters, " Fun ") "|`n"
MsgBox %r%
a1 := StringMod(str, "Rot13")
b1 := StringMod(a1, "Rot13")
a2 := StringMod(str, "Rot13", 7)
b2 := StringMod(a2, "Rot13", 26-7)
MsgBox Rot13:`n%str%`n%a1%`n%b1%`n%a2%`n%b2%
a1 := StringMod(str, "Rot47")
b1 := StringMod(a1, "Rot47")
a2 := StringMod(str, "Rot47", 13)
b2 := StringMod(a2, "Rot47", 94-13)
MsgBox Rot47:`n%str%`n%a1%`n%b1%`n%a2%`n%b2%
}
|
_________________
vPhiLho := RegExReplace("Philippe Lhoste", "^(\w{3})\w*\s+\b(\w{3})\w*$", "$1$2")
Last edited by PhiLho on Sat Mar 04, 2006 3:09 pm; edited 3 times in total |
|
| Back to top |
|
 |
Laszlo
Joined: 14 Feb 2005 Posts: 4078 Location: Pittsburgh
|
Posted: Fri Mar 03, 2006 3:34 pm Post subject: |
|
|
Nice functions!
…you could save a few lines at setting "o", with Shimanov's trick | Code: | | o := 65*(64<char && char<91)+97*(96<char && char<123) |
|
|
| Back to top |
|
 |
PhiLho
Joined: 27 Dec 2005 Posts: 6721 Location: France (near Paris)
|
Posted: Fri Mar 03, 2006 4:12 pm Post subject: |
|
|
Thanks!
I like the If char between 65 and 87 as it was quite readable.
But I like the logic behind the expression, and using Asc calls, it is self-documenting (more or less!). And since this function is growing, saving some lines isn't too bad.
It is perhaps a bit slower, calling Asc 6 times on each loop, but I doubt it is noticeable, we rarely Rot13 whole books... _________________
vPhiLho := RegExReplace("Philippe Lhoste", "^(\w{3})\w*\s+\b(\w{3})\w*$", "$1$2") |
|
| Back to top |
|
 |
SKAN
Joined: 26 Dec 2005 Posts: 6264
|
Posted: Fri Mar 03, 2006 7:50 pm Post subject: |
|
|
Dear PhiLho,
Rot13, Rot47 and variants: I admit that I never knew about it, Thanks for Info + Function
| You wrote: | | For consistency, I would have integrated Flip into the loop: |
I have in my mind of adding more functionality to StringMod() like
StringMod(String,"Upper")
StringMod(String,"Lower")
StringMod(String,"Title") or StringMod(String,"Proper")
which does not require the string parsing loop & so I thought FLIP may stay out of the parsing loop.
More functionality can be added, like
StringMod(String,"OnlyDigits") ; _chars should be assigned 0123456789
StringMod(String,"A2Z") ; _chars should be assigned ABCDEFGHIJKLMNOPQRSTUVWXYZ
Instead of the present way
StringMod(String,"Only","0123456789")
StringMod(String,"Only","ABCDEFGHIJKLMNOPQRSTUVWXYZ"
Also, I am thinking about consolidating independent AHK string commands into a few but powerful functions like
writing one single function StringGet() for
StringGet(String,"Right",1)
StringGet(String,"Left",1)
StringGet(String,"Middle",10,1)
etc.
| You wrote: | | Flip function is probably not of huge utility, except perhaps to perform some AHK functions that doesn't provide a facility starting from the right of the string |
Yes! I agree Flip is a fancy option, but maybe it will be useful for those writing word based games in AHK ( like me ).
Regards,
Note: If anybody interested in Anagram/Jumbled word finder let me know. I've written a function for it _________________
 |
|
| Back to top |
|
 |
Laszlo
Joined: 14 Feb 2005 Posts: 4078 Location: Pittsburgh
|
Posted: Fri Mar 03, 2006 8:25 pm Post subject: |
|
|
| Goyyah wrote: | StringGet(String,"Right",1)
StringGet(String,"Left",1)
StringGet(String,"Middle",10,1) | You could even save the second parameter. Specify the start and end character index, where a negative index should mean counting from the end. If you call it with 2 parameters, StringGet(String,3) = StringGet(String,1,3), that is, "3 chars from Left"; or StringGet(String,-2) = StringGet(String,-2,-1), that is, "2 chars from Right". I used these in the list manipulation library. |
|
| Back to top |
|
 |
SKAN
Joined: 26 Dec 2005 Posts: 6264
|
Posted: Fri Mar 03, 2006 8:55 pm Post subject: |
|
|
Dear Laszlo,
Offtopic: I just visited List manipulation functions. I am yet to get comfortable with Listview but your functions will be of a great help to me!
| You wrote: | You could even save the second parameter. Specify the start and end character index, where a negative index should mean counting from the end.If you call it with 2 parameters,
StringGet(String,3) = StringGet(String,1,3), that is, "3 chars from Left"; or
StringGet(String,-2) = StringGet(String,-2,-1), that is, "2 chars from Right".
I used these in the list manipulation library. |
Thats a good idea!. What do you suggest for StringMid()
Regards,  _________________
 |
|
| Back to top |
|
 |
Titan
Joined: 11 Aug 2004 Posts: 5382 Location: /b/
|
Posted: Fri Mar 03, 2006 9:26 pm Post subject: |
|
|
Nice funciton
Here is my improved rewrite - it works slightly faster, is smaller in code size and supports character rotation of n, Flip, Omit, Replace and Only (the first few lines is for demonstration): | Code: | str = The name of the variable whose contents will be analyzed.
r := "Flip:`t" . StringMod(str, "Flip") . "`nOmit "" "":`t"
. StringMod(str, "Omit", " ") . "`nRot13:`t" . StringMod(str, "Rot13")
. "`nRot47:`t" . StringMod(str, "Rot47") . "`nOnly ..:`t" . StringMod(str, "only", "aeiou")
MsgBox, 64, StringMod(), Original:`t%str%`n`n%r%
StringMod(s, m="", ch="", rc="") { ; enhanced by Titan :)
xAT := A_AutoTrim
AutoTrim, Off
IfEqual, ch, , SetEnv, ch, %A_Space%
IfEqual, rc, , SetEnv, rc, _
Loop Parse, s
If InStr(m, "Rot") {
StringReplace, n, m, Rot
l := Asc(A_LoopField)
Loop, 2 {
If (A_Index = 1) {
f = 65
c = 90
} Else {
f = 97
c = 122
} If (l >= f and l <= c) {
l += n
Loop
If (l > c)
l := l - c + f - 1
Else
Break
} }
e := e . Chr(l)
} Else If m =Flip
e =%A_LoopField%%e%
Else
If InStr(ch, A_LoopField) {
If m =Only
e =%e%%A_LoopField%
Else If m =Replace
e = %e%%rc%
} Else If m !=Only
e =%e%%A_LoopField%
Autotrim, % xAT
Return, e
} |
Edit: updated rotation algorithm _________________

Last edited by Titan on Sat Mar 04, 2006 12:50 pm; edited 1 time in total |
|
| Back to top |
|
 |
SKAN
Joined: 26 Dec 2005 Posts: 6264
|
Posted: Fri Mar 03, 2006 9:54 pm Post subject: |
|
|
Dear Titan
Great work! _________________
 |
|
| Back to top |
|
 |
SKAN
Joined: 26 Dec 2005 Posts: 6264
|
Posted: Fri Mar 03, 2006 10:00 pm Post subject: |
|
|
Every String in my Original Code has been modified except for the function name StringMod()
Regards  _________________
 |
|
| Back to top |
|
 |
Titan
Joined: 11 Aug 2004 Posts: 5382 Location: /b/
|
Posted: Fri Mar 03, 2006 10:31 pm Post subject: |
|
|
| Goyyah wrote: | Every String in my Original Code has been modified except for the function name StringMod() | Yep, it was a complete rewrite thanks for the credit.
Btw. that smilie icon is awesome  _________________
 |
|
| Back to top |
|
 |
SKAN
Joined: 26 Dec 2005 Posts: 6264
|
Posted: Sat Mar 04, 2006 12:17 pm Post subject: |
|
|
Dear Titan,
StringMod("HELLO","Rot13")
should return "URYYB"
whereas
it returns "URYY\"
Please clarify..
Also, I want to put a link for a downloadable .AHK in the first post,
so please host it and provide me a link to the same.
Regards,
Edit: Titan updated his code _________________

Last edited by SKAN on Sat Mar 04, 2006 1:10 pm; edited 1 time in total |
|
| Back to top |
|
 |
PhiLho
Joined: 27 Dec 2005 Posts: 6721 Location: France (near Paris)
|
Posted: Sat Mar 04, 2006 12:38 pm Post subject: |
|
|
Well, Titan's code is short and al, but it doesn't do true Rot13, which acts only on alphabetic characters and replaces them only by alphabetic chars...
So it won't decode Rot13-encoded secret messages given on Usenet (or elsewhere). _________________
vPhiLho := RegExReplace("Philippe Lhoste", "^(\w{3})\w*\s+\b(\w{3})\w*$", "$1$2") |
|
| Back to top |
|
 |
|
|
You can post new topics in this forum You can reply to topics in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|