Search code examples
stringsplitnsis

Count and split string with space except if between quotes in NSIS


My question is like Split string on spaces in Java, except if between quotes (i.e. treat \"hello world\" as one token) but in NSIS way. Hopefully without any external plugins.

How do I split a String based on space but take quoted substrings as one word?

Example:

Location "Welcome to india" Bangalore Channai "IT city"  Mysore

it should be stored in ArrayList as

Location
Welcome to india
Bangalore
Channai
IT city
Mysore

Solution

  • There is no array support without plugins so I left out the array part.

    Any string operation can be performed with the 3 basic string functions in NSIS (StrLen, StrCpy and StrCmp):

    !include LogicLib.nsh
    Function SplitArg
    Exch $0 ; str
    Push $1 ; inQ
    Push $3 ; idx
    Push $4 ; tmp
    StrCpy $1 0
    StrCpy $3 0
    loop:
        StrCpy $4 $0 1 $3
        ${If} $4 == '"'
            ${If} $1 <> 0 
                StrCpy $0 $0 "" 1
                IntOp $3 $3 - 1
            ${EndIf}
            IntOp $1 $1 !
        ${EndIf}
        ${If} $4 == '' ; The end?
            StrCpy $1 0
            StrCpy $4 ' '
        ${EndIf} 
        ${If} $4 == ' '
        ${AndIf} $1 = 0
            StrCpy $4 $0 $3
            StrCpy $1 $4 "" -1
            ${IfThen} $1 == '"' ${|} StrCpy $4 $4 -1 ${|}
            killspace:
                IntOp $3 $3 + 1
                StrCpy $0 $0 "" $3
                StrCpy $1 $0 1
                StrCpy $3 0
                StrCmp $1 ' ' killspace
            Push $0 ; Remaining
            Exch 4
            Pop $0
            StrCmp $4 "" 0 moreleft
                Pop $4
                Pop $3
                Pop $1
                Return
            moreleft:
            Exch $4
            Exch 2
            Pop $1
            Pop $3
            Return
        ${EndIf}
        IntOp $3 $3 + 1
        Goto loop
    FunctionEnd
    
    
    Section
    push 'Location "Welcome to india" Bangalore Channai "IT city"  Mysore'
    loop:
        call SplitArg
        Pop $0
        StrCmp $0 "" done
        DetailPrint Item=|$0|
        goto loop
    done:
    SectionEnd