AutoHotkey Community

It is currently May 26th, 2012, 8:50 pm

All times are UTC [ DST ]




Post new topic Reply to topic  [ 15 posts ] 
Author Message
PostPosted: June 17th, 2009, 6:27 pm 
Offline

Joined: June 10th, 2009, 6:34 pm
Posts: 102
spaces as delimiters except when quotes are encountered.

For example:

incoming_string = she sells sea shells "by the sea shore"

After running through string split I would like to produce the following array:

out_array[0] = she
out_array[1] = sells
out_array[2] = sea
out_array[4] = shells
out_array[5] = by the sea shore

Is it possible to get StringSplit to behave like that? Or to accomplish that using some other command?


Last edited by lrh9 on September 1st, 2009, 10:57 am, edited 1 time in total.

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: June 17th, 2009, 6:34 pm 
Offline

Joined: June 10th, 2009, 6:34 pm
Posts: 102
I looked at loop parsing for strings. It appears that both of them aren't up to the task. I think I'm going to have to write a custom function to be able to do what I described.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: June 17th, 2009, 7:06 pm 
Offline
User avatar

Joined: November 2nd, 2008, 4:23 pm
Posts: 2906
Location: 127.0.0.1
Code:
split("she sells sea shells ""by the sea shore""", "output_array")
Loop 5
  Msgbox % output_array%A_Index%
ExitApp
Return

split(String, output_array) {
global
StringSplit, String, String, "
StringSplit, %output_array%, String1, %A_Space%
Pos := %output_array%0
%output_array%%Pos% := String2
Return
}
There has to be a better way to do this but it works.

_________________
aboutscriptappsscripts
Any code ⇈ above ⇈ requires AutoHotkey_L to run


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: June 17th, 2009, 7:24 pm 
Offline

Joined: April 8th, 2009, 8:23 pm
Posts: 3036
Location: Rio de Janeiro - RJ - Brasil
Frankie wrote:
Code:
split("she sells sea shells ""by the sea shore""", "output_array")
Loop 5
  Msgbox % output_array%A_Index%
ExitApp
Return

split(String, output_array) {
global
StringSplit, String, String, "
StringSplit, %output_array%, String1, %A_Space%
Pos := %output_array%0
%output_array%%Pos% := String2
Return
}

I suggest not using "global".
Code:
split("she sells sea shells ""by the sea shore""", "outArray")
Loop 5
  Msgbox % outArray%A_Index%
ExitApp
Return

split(String, output_array) {
local Pos, String1, String2
StringSplit, String, String, "
StringSplit, %output_array%, String1, %A_Space%
Pos := %output_array%0
%output_array%%Pos% := String2
Return
}

_________________
"Read the manual. Read it again. Search the forum.
Try something before asking. Show what you've tried.
"
Image
Antonio França
My stuff: Google Profile


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: June 17th, 2009, 8:56 pm 
Offline

Joined: October 7th, 2006, 4:50 pm
Posts: 3157
Location: MN, USA
Here's a way to do it with a loop (creates a global array; array0 contains the number of elements).
Code:
string = she sells sea shells "by the sea shore"

Loop, Parse, string, %A_Space%
{
 If quote {
  array%i% .= A_Space A_LoopField
  If InStr(A_LoopField,"""")
   quote = 0
  continue
 }
 i++
 array0 := i
 array%i% := A_LoopField
 If InStr(A_LoopField,"""")
  quote = 1
}

Loop,% array0
 list .= "array" A_Index " = " array%A_Index% "`n"
MsgBox, %list%

EDIT: here's the same thing, wrapped in a function.
Code:
string = she sells sea shells "by the sea shore"

QSplit(string)
Loop,% array0
 list .= "array" A_Index " = " array%A_Index% "`n"
MsgBox, %list%
return

QSplit(string) {
 local quote, i
 Loop, Parse, string, %A_Space%
 {
  If quote {
   array%i% .= A_Space A_LoopField
   If InStr(A_LoopField,"""")
    quote = 0
   continue
  }
  i++
  array0 := i
  array%i% := A_LoopField
  If InStr(A_LoopField,"""")
   quote = 1
 }
}


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: June 18th, 2009, 6:18 pm 
Offline

Joined: June 10th, 2009, 6:34 pm
Posts: 102
Is there a built in variable containing the escape character for the script/autohotkey?


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: June 18th, 2009, 7:13 pm 
Offline

Joined: October 7th, 2006, 4:50 pm
Posts: 3157
Location: MN, USA
#EscapeChar (and explanation of escape sequences)


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: June 22nd, 2009, 3:44 am 
Offline

Joined: June 10th, 2009, 6:34 pm
Posts: 102
The above code looks good, but my main problem with it is that I think they would all break the string at a quote if it appeared between the delimiting quotes.

For instance, they would break up:

she sells sea shells "by the "sea" shore"

into:

1: she
2: sells
3: sea
4: shells
5: by the
6: sea
7: shore

Is there a way around it? I did something like this in c++, but I'm new to autohotkey. The way I did it in c++ was to have the substrings created by having them wrapped in single quotes and then requiring strings quoted inside to be wrapped in an escape sequence. In c++ it would look something like this:

she sells sea shells "by the \"sea\" shore"

So in autohotkey it would look like:

she sells sea shells "by the `"sea`" shore"

And they would both display as:

1: she
2: sells
3: sea
4: shells
5: by the "sea" shore

Sorry for being so picky, but I really think this is what I need.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: June 22nd, 2009, 4:26 am 
Offline

Joined: June 10th, 2009, 6:34 pm
Posts: 102
I think I defined the necessary algorithm in pseudo-code:

Note: A single quote here is defined as a quote (`") in the string not preceded by an accent (``). This would need to be coded to. (Probably by finding each quote and then check the character immediately before it.)

While there is text in the string.
1) Search the string for a single quote. Assign the portion before the quote (or the entire string if there is not one) to a temporary variable and stringsplit that to an output array variable using the space character as the delimiter. Remove the string stored in the temporary variable from the original string. (If there was no quote, all text should have been stored in the temporary variable and then removed from the original string, meaning the loop would break.)
2) Search the string for another single quote. If one is encountered, append it to the output array variable. If not, there are two options. Treat the rest of the string as if it had a single quote at the end. (Meaning the rest of the string would be one substring.) OR discard the first quote and split the remaining text using spaces. This behavior should be user defined. I'd probably go with the first option as a default. Remove the portion of the string that was parsed from the string.
3) This will repeat until nothing remains in the string.

Example input and output:

Input = she sells sea shells "by the `"sea`" shore"
(Scan process)
Tempvar = she sells sea shells
stringsplit output tempvar " "
Output1 = she
Output2 = sells
Output3 = sea
Output4 = shells
Input = "by the `"sea`" shore"
(Scan process)
Tempvar = by the "sea" shore
Output5 = by the "sea" shore
Input =
Return


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: June 22nd, 2009, 4:52 am 
Offline

Joined: October 7th, 2006, 4:50 pm
Posts: 3157
Location: MN, USA
A minor addition to my original code might be acceptable.
Code:
strings =
(
she sells sea shells by the sea shore
she sells sea shells by the "sea" shore
she sells sea shells "by the sea shore"
she sells sea shells "by the "sea" shore"
she sells sea shells "by "the sea" shore"
)
Loop, Parse, strings, `n, `r
 MsgBox,% QSplit(A_LoopField)
return

QSplit(string) {
 local quote, list, i
 Loop, Parse, string, %A_Space%
 {
  If !quote {
   i++
   array0 := i
   array%i% := A_LoopField
  }
  Else array%i% .= A_Space A_LoopField
  If InStr(A_LoopField,"""") = 1
   quote++
  If (InStr(A_LoopField,"""","",0) = StrLen(A_LoopField))
   quote--
 }
 Loop,% array0
  list .= "array" A_Index " = " array%A_Index% "`n"
 Return, list
}


Edit1: updated code.
Edit2: updated code again.
Edit3: shortened code.


Last edited by jaco0646 on June 22nd, 2009, 6:09 pm, edited 2 times in total.

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: June 22nd, 2009, 9:58 am 
Online
User avatar

Joined: December 26th, 2005, 4:40 pm
Posts: 8776
Code:
String = she sells sea shells "by the "sea" shore"
MsgBox, % DelimitParameters( String, "`n" )

DelimitParameters( CommandLine,D="|" ) {     ; Supplementary function for GetCommandLine()
 tempVar := CommandLine           ; www.autohotkey.com/forum/viewtopic.php?p=232199#232199
 Loop {
 StringReplace,tempVar,tempVar,%Param%
 CommandLine := DllCall( "shlwapi\PathGetArgsA", Str,CommandLine,Str )
 StringReplace,Param,tempVar,%CommandLine%
 DllCall( "shlwapi\PathUnquoteSpacesA", Str,Param )
 IfEqual,Param,,Return SubStr(DelimitedString,2)
 DelimitedString = %DelimitedString%%D%%Param%
}}

_________________
URLGet - Internet Explorer based Downloader
StartEx - Portable Shortcut Link


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: June 22nd, 2009, 3:45 pm 
Offline

Joined: October 7th, 2006, 4:50 pm
Posts: 3157
Location: MN, USA
I had to update my above code again; it didn't work with all combinations of quotations, so I've added some different strings to be checked. Note that my function fails if a string contains a quote between two spaces ( " ) since spaces are used as delimiters. SKAN's function won't handle it either.

@ SKAN
Your function also fails for me on multi-word nested quotes (the last example string in my above code).


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: June 22nd, 2009, 4:23 pm 
Online
User avatar

Joined: December 26th, 2005, 4:40 pm
Posts: 8776
jaco0646 wrote:
@ SKAN
Your function also fails for me on multi-word nested quotes (the last example string in my above code).


My function tries to reproduce the results one would get by passing the string as a parameter to the following AHK script:

Code:
Loop %0%
 P .= %A_Index% "`n"
MsgBox, % P


I presumed lrh9's incoming_string was actually command-line parameters.. if not, my code would not be of much use, I guess.

Thanks for testing my code. :)


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: September 1st, 2009, 11:20 am 
Offline

Joined: June 10th, 2009, 6:34 pm
Posts: 102
Finally realized the solution a couple of days ago. (All though it looks like someone has solved the problem since the last time I checked the post.) Instead of using spaces to divide the individual fields and quotes to encapsulate fields with spaces, use a non-printing ascii character to separate fields such as the Unit Separator.

Code:
Variable := "she" . chr(31) . "sells" . chr(31) . "sea" . chr(31) . "shells" . chr(31) . "by the sea shore"

msgbox %Variable%

A_UnitSeparator := chr(31)

msgbox %A_UnitSeparator%

StringSplit, OutputArray, Variable, %A_UnitSeparator%,

msgbox %OutputArray0%

Loop, %OutputArray0%
{
    msgbox % OutputArray%A_Index%
}


I don't discount the other solution just yet though. All though this method allows for the simple serialization and deserialization of strings within a program, it would be entirely inefficient or impossible to force users to input data this way. The other solution allows for the processing of regular user input.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: January 19th, 2011, 6:21 pm 
Offline

Joined: January 19th, 2011, 3:08 pm
Posts: 1
Thanks lrh9, I registered to this forum to thank you.
Your last solution is what I needed.
Let me point out that you don't need to use a strange character like the chr(31) (passed with a variable), and that this one works too:

Code:
Variable := "she|sells|sea|shells|by the sea shore"

msgbox %Variable%

A_UnitSeparator := "|"

msgbox %A_UnitSeparator%

StringSplit, OutputArray, Variable, %A_UnitSeparator%,

msgbox %OutputArray0%

Loop, %OutputArray0%
{
    msgbox % OutputArray%A_Index%
}


Report this post
Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 15 posts ] 

All times are UTC [ DST ]


Who is online

Users browsing this forum: BrandonHotkey, coinman, Leef_me, Yahoo [Bot] and 59 guests


You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Group