Splitting Strings Topic is solved

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
User avatar
L40P
Posts: 19
Joined: 05 Jul 2016, 15:49

Splitting Strings

12 Sep 2017, 09:11

Ok, so I want to try to build myself a little Timer. I have an Inputbox and a Submit Button. I want to enter the time in a format like 1h20m30s for 1 hour, 20 minutes and 30 seconds, but I have no clue of how to separate that string. I thougth about learning the RegEx thing, but I just don't understand it.
Thanks for help!


When nothing works I'll just separate the numbers by a space.
User avatar
Gio
Posts: 1247
Joined: 30 Sep 2013, 10:54
Location: Brazil

Re: Splitting Strings

12 Sep 2017, 09:19

Hello L40P.

StringSplit is the command you are looking for.

Analyze the string 1h20m30s and you will see that it follows a pattern. The hour is always to the left to the letter h, the minute is always to the left of the letter m and to the right of the letter h and the second is always to the left of the letter s. This is all you need to plan you routine.

First, separate the string based on letter h.
The first field should contain the hour:

Code: Select all

String := "1h20m30s"
StringSplit, String_, String, h
msgbox % String_1
Next, separate the remaining string based on the letter m.
The new first field should contain the minute:

Code: Select all

String := "1h20m30s"
StringSplit, String_, String, h
msgbox % String_1
StringSplit, String_2_, String_2, m
msgbox % String_2_1
And finally, separate the last remaining part of the string based on the letter s.
The new first field should contain the second:

Code: Select all

String := "1h20m30s"
StringSplit, String_, String, h
msgbox % String_1
StringSplit, String_2_, String_2, m
msgbox % String_2_1
StringSplit, String_2_2_, String_2_2, s
msgbox % String_2_2_1
Thats all there is to it. For a true finale, you should also change the input time and run a few tests to make sure everything works as expected.

Code: Select all

String := "7h30m45s"
StringSplit, String_, String, h
msgbox % String_1
StringSplit, String_2_, String_2, m
msgbox % String_2_1
StringSplit, String_2_2_, String_2_2, s
msgbox % String_2_2_1

The key to plan a routine like that is to isolate all the possible patterns and plan the routine based on them. Thus, if the string can, in any possible way, follow a different pattern, you have to account for that too. Otherwise, you are good to go.

Best wishes.
Last edited by Gio on 12 Sep 2017, 09:25, edited 1 time in total.
User avatar
DyaTactic
Posts: 221
Joined: 04 Apr 2017, 05:52

Re: Splitting Strings

12 Sep 2017, 09:24

I made a timer just like that. As the input I used two ways. 1) Use a different text input for every different unit (h/m/s) and 2) a standard DateTime control.
Different controls for every unit: https://gyazo.com/9906c3b3a1d1152fe9ff203685675930
DateTime control: https://gyazo.com/58a71dd2a88c83fed8f3dbf7f40d2396
Last edited by DyaTactic on 12 Sep 2017, 11:09, edited 1 time in total.
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Splitting Strings  Topic is solved

12 Sep 2017, 09:56

3 ways. Note: StringSplit is being removed in AHK v2, so I would recommend StrSplit.

The RegExMatch output to variables mode is due to be removed in AHK v2, so I would use the object mode.

Code: Select all

q::
vTime := "1h20m30s"
oTemp := StrSplit(vTime, ["h","m","s"])
vSec := oTemp.1*3600 + oTemp.2*60 + oTemp.3
MsgBox, % oTemp.1 " " oTemp.2 " " oTemp.3 "`r`n" vSec
return

w::
vTime := "1h20m30s"
RegExMatch(vTime, "O)(\d*)h(\d*)m(\d*)s", o)
vSec := 0
;vSec := o.Value(1)*3600 + o.Value(2)*60 + o.Value(3)
vSec := o.1*3600 + o.2*60 + o.3
MsgBox, % vTime "`r`n" vSec
return

e::
vTime := "1h20m30s"
vTime := RegExReplace(vTime, "[hms]", ",")
vSec := 0
Loop, Parse, vTime, % ","
	vSec += A_LoopField * 60**(3-A_Index)
MsgBox, % vTime "`r`n" vSec
return
[EDIT:] Here's another approach:

Code: Select all

q::
vTime := "1h20m30s"
vSec := 0
Loop, Parse, vTime, hms
	vSec += Format("{:i}", A_LoopField * 60**(3-A_Index))
MsgBox, % vTime "`r`n" vSec
return
Last edited by jeeswg on 08 Apr 2018, 18:00, edited 2 times in total.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
L40P
Posts: 19
Joined: 05 Jul 2016, 15:49

Re: Splitting Strings

12 Sep 2017, 11:11

Ok, I found the String Parsing Loop and figured out myself how to do it using that.
But I guess the methods by @jeeswg and @Gio would work aswell.
Thank you guys!
eagerahk
Posts: 122
Joined: 02 Dec 2015, 06:27

Re: Splitting Strings

12 Sep 2017, 12:02

hi, jeeswg,
The following does not work as expected:

Code: Select all

vTime := "this is a book 12h25m30s"
oTemp := StrSplit(vTime, ["is","book","25"])
MsgBox, % oTemp.1 "-" oTemp.2 "-" oTemp.3  "-" oTemp.4   "-" oTemp.5
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Splitting Strings

12 Sep 2017, 12:07

The problem is probably 'is', it appears in the word 'this' as well as as a single word. Possibly this will work for you:

Code: Select all

q::
vTime := "this is a book 12h25m30s"
oTemp := StrSplit(vTime, [" is "," book ","25"])
MsgBox, % oTemp.1 "-" oTemp.2 "-" oTemp.3  "-" oTemp.4   "-" oTemp.5
return
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
eagerahk
Posts: 122
Joined: 02 Dec 2015, 06:27

Re: Splitting Strings

12 Sep 2017, 12:25

Though " is "," book ","25" works here, however the real parse needs to take care of "is","book","25".
And the expected result should be th, is a, 12h, and m30h.
If not, the parse result can't be 100% sure right.
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Splitting Strings

12 Sep 2017, 12:35

With RegEx you can you use \b to represent boundary characters, that might help. Essentially you can replace certain strings with an unused character, and then use that unused character as one of the delimiter strings.

Regular Expressions (RegEx) - Quick Reference
https://autohotkey.com/docs/misc/RegEx-QuickRef.htm

Code: Select all

q::
vTime := "this is a book 12h25m30s"
vTime := RegExReplace(vTime, "(?<!\b)is\b", "|")
MsgBox, % vTime
oTemp := StrSplit(vTime, ["|","book","25"])
MsgBox, % "|" oTemp.1 "|" oTemp.2 "|" oTemp.3 "|" oTemp.4 "|" oTemp.5 "|"
return

w::
vTime := "this is a book 12h25m30s"
vTime := RegExReplace(vTime, "\bis\b", "|")
MsgBox, % vTime
oTemp := StrSplit(vTime, ["|","book","25"])
MsgBox, % "|" oTemp.1 "|" oTemp.2 "|" oTemp.3 "|" oTemp.4 "|" oTemp.5 "|"
return
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
eagerahk
Posts: 122
Joined: 02 Dec 2015, 06:27

Re: Splitting Strings

12 Sep 2017, 12:43

In the case of oTemp := StrSplit(vTime, ["h","m","s"]), it is possible that the string may have more than one "h", or "m", or "s"..just like in my case I have two "is".
Therefore making it work for "is","book","25" is useful.
In IBM's REXX, the prase is intuitively simple--parse vtime part1 'is' part2 'book' part3 '25' part4. Thanks
Last edited by eagerahk on 20 Sep 2017, 21:43, edited 1 time in total.
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Splitting Strings

12 Sep 2017, 12:57

Any function has to have some logic, so if you can figure out and describe the logic involved, then perhaps AutoHotkey can replicate it somehow. StrSplit is very simple, every time it sees a string it treats it as a delimiter.

One possible other thing to mention is StrReplace, you can specify to replace the first n instances of a string.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
eagerahk
Posts: 122
Joined: 02 Dec 2015, 06:27

Re: Splitting Strings

12 Sep 2017, 18:28

Last edited by eagerahk on 20 Sep 2017, 21:44, edited 1 time in total.
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Splitting Strings

12 Sep 2017, 22:42

By following the documentation, I've produced something that should work more or less, or exactly, the same as the Parse function. If there are any slight differences, it shouldn't take very much to alter the code below.

Code: Select all

;based on:
;IBM Knowledge Center - Simple templates for parsing into words
;https://www.ibm.com/support/knowledgecenter/en/SSLTBW_2.1.0/com.ibm.zos.v2r1.ikja300/simtem.htm

q:: ;emulate REXX's Parse but without special trimming of spaces
vText := "this is a book 12h25m30s"
oTemp := StrSplit(vText, " ")
MsgBox, % "|" oTemp.1 "|" oTemp.2 "|" oTemp.3 "|" oTemp.4 "|" oTemp.5 "|"

;specify a maximum of 4 output parts
vUnused := Chr(1)
vText := "this is a book 12h25m30s"
vText := StrReplace(vText, " ", vUnused, "", 3)
oTemp := StrSplit(vText, vUnused)
MsgBox, % "|" oTemp.1 "|" oTemp.2 "|" oTemp.3 "|" oTemp.4 "|" oTemp.5 "|"

;specify a maximum of 1 output part
vUnused := Chr(1)
vText := "this is a book 12h25m30s"
vText := StrReplace(vText, " ", vUnused, "", 0)
oTemp := StrSplit(vText, vUnused)
MsgBox, % "|" oTemp.1 "|" oTemp.2 "|" oTemp.3 "|" oTemp.4 "|" oTemp.5 "|"
return

;==============================

w:: ;emulate REXX's Parse (including special trimming of spaces)
vText := "   this   is   a   book   12h25m30s   "
vText := Trim(RegExReplace(vText, " +", " "))
oTemp := StrSplit(vText, " ")
MsgBox, % "|" oTemp.1 "|" oTemp.2 "|" oTemp.3 "|" oTemp.4 "|" oTemp.5 "|"

;specify a maximum of 4 output parts
vUnused := Chr(1)
vText := "   this   is   a   book   12h25m30s   "
vText := LTrim(vText, " ")
vText := RegExReplace(vText, " +", " ", "", 2)
vText := StrReplace(vText, " ", vUnused, "", 3)
oTemp := StrSplit(vText, vUnused)
MsgBox, % "|" oTemp.1 "|" oTemp.2 "|" oTemp.3 "|" oTemp.4 "|" oTemp.5 "|"

;specify a maximum of 1 output part
vUnused := Chr(1)
vText := "   this   is   a   book   12h25m30s   "
;vText := LTrim(vText, " ")
vText := RegExReplace(vText, " +", " ", "", 0)
vText := StrReplace(vText, " ", vUnused, "", 0)
oTemp := StrSplit(vText, vUnused)
MsgBox, % "|" oTemp.1 "|" oTemp.2 "|" oTemp.3 "|" oTemp.4 "|" oTemp.5 "|"
return
There are two curious features to the Parse function.
- You can do something a bit like the StrSplit function, but for example, specify 4, whereby the first 3 items found have separate variables/keys, but where everything else is put into the 4th variable/key. This is the sort of thing that seems like a good feature to have, however, despite all the things I've done with strings, I can't think of any immediate examples where this would be useful.
- There are various complications to the algorithm, whereby you keep spaces in tact, rather than simply replacing multiple spaces with single spaces at the beginning. Again, I can't see where I'd have very much use for this.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Splitting Strings

13 Sep 2017, 02:06

The main point would be parsing of file formats I guess.
But then again a file format could easily become so complex that you need to use RegEx anyways.
It is probably the best form of StrSplit I have seen so far though.
Recommends AHK Studio
eagerahk
Posts: 122
Joined: 02 Dec 2015, 06:27

Re: Splitting Strings

13 Sep 2017, 02:36

1. The 4th variable/key can later be used for other purposes.
2. REXX function, STRIP, can remove leading/trailing spaces(or both) like, STRIP(' ab c ')-->'ab c' , if necessary.
Last edited by eagerahk on 21 Sep 2017, 10:24, edited 5 times in total.
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Splitting Strings

13 Sep 2017, 07:30

2. Is the same as AutoHotkeys Trim function
Recommends AHK Studio
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Splitting Strings

13 Sep 2017, 12:30

The following function should fully emulate REXX's PARSE function up to 10 delimeters:
You might be intetested in variadic functions.
eagerahk
Posts: 122
Joined: 02 Dec 2015, 06:27

Re: Splitting Strings

14 Sep 2017, 05:36

Thanks for the advices by Jeeswg and Helgef.

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: Google [Bot], jaka1, jschwalbe, marypoppins_1, mikeyww, usser, wilkster and 151 guests