Author Topic: Find a string between delimiter1 and delimiter2  (Read 1567 times)

0 Members and 1 Guest are viewing this topic.

Marc'Antonio Alessi

  • Swamp Rat
  • Posts: 1454
  • Marco
Find a string between delimiter1 and delimiter2
« on: June 22, 2018, 05:58:24 AM »
Is this a good solution?
Code: [Select]
;
; (ALE_String_AfterBeforeDelimiter "123/45/1/2/999 H=9876 W - Foo1" "H=" " ") => "9876"
; (ALE_String_AfterBeforeDelimiter "123/45/1/2/999 H=9876 W - Foo1" "H=" "j") => "9876 W - Foo1"
; (ALE_String_AfterBeforeDelimiter "123/45/1/2/999 H=9876 W - Foo1" "x=" "j") => nil
;
; return nil if first Delimiter not found
; if second Delimiter not found return all string after first Delimiter
;
(defun ALE_String_AfterBeforeDelimiter (InpStr FrtDlm ScdDlm / SttPos EndPos)
  (if (setq SttPos (vl-string-search FrtDlm InpStr))
    (if (setq EndPos (vl-string-search ScdDlm InpStr (+ SttPos (strlen FrtDlm))))
      (substr InpStr (+ 1 SttPos (strlen FrtDlm)) (- EndPos SttPos (strlen ScdDlm) 1))
      (substr InpStr (+ 1 SttPos (strlen FrtDlm)))
    )
  )
)

ronjonp

  • Needs a day job
  • Posts: 7533
Re: Find a string between delimiter1 and delimiter2
« Reply #1 on: June 22, 2018, 10:03:18 AM »
I would think that your second example would return nil since the second delimiter does not exist?
« Last Edit: June 22, 2018, 12:54:19 PM by ronjonp »

Windows 11 x64 - AutoCAD /C3D 2023

Custom Build PC

Marc'Antonio Alessi

  • Swamp Rat
  • Posts: 1454
  • Marco
Re: Find a string between delimiter1 and delimiter2
« Reply #2 on: June 22, 2018, 10:17:00 AM »
I would think that your second example would retuen nil since the second delimiter does not exist?
My current need is to find the string after "H=" and I could have three cases:
Code: [Select]
"123/45/1/2/999 H=9876 W - Foo1"     => 9876
"123/45/1/2/999 H=9876"             => 9876
"123/45/1/2/999 H=9876 "            => 9876

cmwade77

  • Swamp Rat
  • Posts: 1449
Re: Find a string between delimiter1 and delimiter2
« Reply #3 on: June 25, 2018, 05:09:49 PM »
I personally needed something like this, but a bit more robust, so here is what I have come up with. I am sure there are some improvements that could be made to error handling and perhaps to the code itself, but hopefully it gets you going in the right direction.
Code: [Select]
(defun cw_Substring (InputString Delim1 Delim2 Mode TrimMode / Delim1Pos Delim2Pos Results)
    ;Written by Chris Wade - 06/25/2018
    ;If you don't want to use Delim2, use nil for the option
    ;Modes:
    ;       0.1 - Returns string before Delim1
    ;       0.2 - Returns string before Delim2
    ;       1 - Returns String beteen Delim2 and Delim2
    ;       2.1 - Returns String after Delim1
    ;       2.2 - Returns String after Delim2
    ;TrimMode - T will trim spaces out of the results, nil won't
    (if Delim1
        (setq Delim1Pos (vl-string-search Delim1 InputString))
    )
    (if Delim2
        (setq Delim2Pos (vl-String-search Delim2 InputString (+ Delim1Pos 1)))
    )
    (cond
        ((= Mode 0.1);Finds string before Delim1
            (setq Results (substr InputString 1 Delim1Pos))
        )
        ((= Mode 0.2);Finds string before Delim2
            (setq Results (substr InputString 1 Delim2Pos))
        )
        ((= Mode 1);Finds String between Delim1 and Delim2
            (setq Results (substr InputString (+ Delim1Pos 2) (- Delim2Pos (+ Delim1Pos 1))))
        )
        ((= Mode 2.1);Finds string after Delim1
            (setq Results (substr InputString (+ Delim1Pos 1)))
        )
        ((= Mode 2.2);Finds string after Delim2
            (setq Results (substr InputString (+ Delim2Pos 2)))
        )
    )
    (if TrimMode
        (setq Results (vl-string-trim " " Results))
    )
    Results
)

And here is some code you could use to test it with:
Code: [Select]
(defun c:DelimTest (/)
    (setq H "Begin=Between=End1|End2");Change this string to test
    (princ "\nThis is without trimming:")
    (princ "\nBefore first =\n")
    (princ (cw_substring H "=" "|" 0.1 nil))
    (princ "\nBefore |\n")
    (princ (cw_substring H "=" "|" 0.2 nil))
    (princ "\nBefore Second =\n")
    (princ (cw_substring H "=" "=" 0.2 nil))
    (princ "\nBetween = and |\n")
    (princ (cw_substring H "=" "|" 1 nil))
    (princ "\nBetween = and =\n")
    (princ (cw_substring H "=" "=" 1 nil))
    (princ "\nAfter first =\n")
    (princ (cw_substring H "=" "|" 2.1 nil))
    (princ "\nAfter |\n")
    (princ (cw_substring H "=" "|" 2.2 nil))
    (princ "\nAfter second =\n")
    (princ (cw_substring H "=" "=" 2.2 nil))
    (princ "\nThis is with trimming:")
    (princ "\nBefore first =\n")
    (princ (cw_substring H "=" "|" 0.1 T))
    (princ "\nBefore |\n")
    (princ (cw_substring H "=" "|" 0.2 T))
    (princ "\nBefore Second =\n")
    (princ (cw_substring H "=" "=" 0.2 T))
    (princ "\nBetween = and |\n")
    (princ (cw_substring H "=" "|" 1 T))
    (princ "\nBetween = and =\n")
    (princ (cw_substring H "=" "=" 1 T))
    (princ "\nAfter first =\n")
    (princ (cw_substring H "=" "|" 2.1 T))
    (princ "\nAfter |\n")
    (princ (cw_substring H "=" "|" 2.2 T))
    (princ "\nAfter second =\n")
    (princ (cw_substring H "=" "=" 2.2 T))
    (princ)
)

Marc'Antonio Alessi

  • Swamp Rat
  • Posts: 1454
  • Marco
Re: Find a string between delimiter1 and delimiter2
« Reply #4 on: June 26, 2018, 12:35:25 PM »
Your version use only 1 caracter for delimitier:
Comando: (ALE_String_AfterBeforeDelimiter "123/45/1/2/999 H=9876W - Foo1" "H=" "W")
"9876"
Comando: (cw_substring "123/45/1/2/999 H=9876W - Foo1" "H=" "W" 1 nil)
"=9876"
Code: [Select]
; New Version 20180626
; (ALE_String_BetweenDelimiters "123/45/1/2/999 H=9876 W - Foo1" "H=" " "  ) => "9876"
; (ALE_String_BetweenDelimiters "123/45/1/2/999 H=9876 W - Foo1" "H=" "j"  ) => "9876 W - Foo1"
; (ALE_String_BetweenDelimiters "123/45/1/2/999 H=9876 W - Foo1" "H=" " - ") => "9876 W"
; (ALE_String_BetweenDelimiters "123/45/1/2/999 H=9876 W - Foo1" "x=" "j"  ) => nil
;
; return nil if first Delimiter not found
; if second Delimiter not found return all string after first Delimiter
;
(defun ALE_String_BetweenDelimiters (InpStr FrtDlm ScdDlm / SttPos EndPos)
  (if (setq SttPos (vl-string-search FrtDlm InpStr))
    (if (setq EndPos (vl-string-search ScdDlm InpStr (+ SttPos (strlen FrtDlm))))
      (substr InpStr (+ 1 SttPos (strlen FrtDlm)) (- EndPos SttPos 2))
      (substr InpStr (+ 1 SttPos (strlen FrtDlm)))
    )
  )
)

cmwade77

  • Swamp Rat
  • Posts: 1449
Re: Find a string between delimiter1 and delimiter2
« Reply #5 on: June 26, 2018, 02:44:29 PM »
Quite true, as that is all that my needs were, but this code should work with delimiters of any length:
Code: [Select]
(defun cw_Substring (InputString Delim1 Delim2 Mode TrimMode / Delim1Pos Delim2Pos Delim1PosEnd Delim2PosEnd Results)
    ;Written by Chris Wade - 06/25/2018
    ;If you don't want to use Delim2, use nil for the option
    ;Modes:
    ;       0.1 - Returns string before Delim1
    ;       0.2 - Returns string before Delim2
    ;       1 - Returns String beteen Delim2 and Delim2
    ;       2.1 - Returns String after Delim1
    ;       2.2 - Returns String after Delim2
    ;TrimMode - T will trim spaces out of the results, nil won't
    (if Delim1
        (setq Delim1Pos (vl-string-search Delim1 InputString)
              Delim1PosEnd (+ Delim1Pos (strlen Delim1))
        )
    )
    (if Delim2
        (setq Delim2Pos (vl-String-search Delim2 InputString (+ Delim1Pos 1))
              Delim2PosEnd (+ Delim2Pos (strlen Delim2))
        )
    )
        (cond
        ((= Mode 0.1);Finds string before Delim1
            (setq Results (substr InputString 1 Delim1Pos))
        )
        ((= Mode 0.2);Finds string before Delim2
            (setq Results (substr InputString 1 Delim2Pos))
        )
        ((= Mode 1);Finds String between Delim1 and Delim2
            (setq Results (substr InputString (+ Delim1PosEnd 1) (- Delim2Pos Delim1PosEnd)))
        )
        ((= Mode 2.1);Finds string after Delim1
            (setq Results (substr InputString (+ Delim1PosEnd 1)))
        )
        ((= Mode 2.2);Finds string after Delim2
            (setq Results (substr InputString (+ Delim2PosEnd 1)))
        )
    )
    (if TrimMode
        (setq Results (vl-string-trim " " Results))
    )
    Results
)