String Operations

<< Click to Display Table of Contents >>

Navigation:  3. Script Language > String commands > !STR.- String Command > Instring - Find Commands >

String Operations

STR.XInstr

Previous Top Next


MiniRobotLanguage (MRL)

 

STR.XInstr

Case-Sensitive Nth String Search

 

Intention

This command searches for the nth occurrence of a specified string (P2) within a source string (P1), starting from an optional position (P4). The occurrence number is specified by P3 (positive for left-to-right counting, negative for right-to-left counting). An optional overlap flag (P5) allows overlapping matches (default FALSE).

The search is case-sensitive (e.g., "Hello" does not match "hello"). The result is the 1-based position of the nth match (or 0 if not found), placed on the Top of Stack (TOS) or in an optional variable (P6).

If P4 is positive (or 0, defaults to 1), it searches left-to-right from that position. If negative (e.g., -1), it searches right-to-left from the end (or |P4| bytes from end). The result is always a 1-based position from the start of the string.

Overlap (P5=1) allows counting overlapping occurrences (e.g., "aa" in "aaa" counts 2 with overlap, 1 without). This command is useful for finding specific instances of a substring in text processing tasks, such as parsing logs or structured data, without modifying the source string.

 

Schematic (Forward and Reverse Nth Search with Overlap)

Source: aaa

Search: aa, N=2, Start=1, Overlap=1 (LTR) --> Pos=2

Search --> |a|a|a|

 ^ ^ (1st at 1, 2nd at 2 with overlap)

Search: aa, N=2, Start=-1, Overlap=1 (RTL) --> Pos=1

Search <-- |a|a|a|

 ^ ^ (2nd at 1 from end)

Without overlap (P5=0): Counts 1 (at 1 or 2, depending on direction).

 

Syntax

 

STR.XInstr|P1|P2|P3[|P4][|P5][|P6]

 

Parameter Explanation

 

P1 - (Source String) The main string to search within. Variable or literal.

P2 - (Search String) The string to search for. Variable or literal.

P3 - (Occurrence Number) Numeric, nth occurrence (positive for left-to-right counting, negative for right-to-left counting).

P4 - (Optional Start Position) Numeric, 1-based (default 1). If negative, searches right-to-left from end or |P4| bytes from end.

P5 - (Optional Overlap Flag) Numeric, 1 to allow overlapping matches (default 0).

P6 - (Optional Result Variable) Variable to store the result (position or 0).

 

Examples

 

' Forward search for 2nd occurrence to TOS

$$TXT=HelloWorldHello

$$SEA=Hello

STR.XInstr|$$TXT|$$SEA|2|1

POP.$$RES

' $$RES = 11 (2nd "Hello")

 

' Reverse search for 2nd occurrence to variable

$$TXT=HelloWorldHello

$$SEA=Hello

STR.XInstr|$$TXT|$$SEA|-2|-1|0|$$POS

' $$POS = 1 (2nd "Hello" from end)

 

' Forward search with overlap for 2nd aa in aaa (overlap=1, pos=1)

$$TXT=aaa

$$SEA=aa

STR.XInstr|$$TXT|$$SEA|2|1|1

POP.$$RES

' $$RES = 2 (2nd "aa" with overlap)

 

 

' =================================================================

' SELF-VALIDATING TEST SCRIPT for STR.XInstr (Unified Nth String Search)

' Purpose: Verify forward/reverse search using P3 sign, P4 dual meaning,

' overlap, and edge cases. Case-sensitive only.

' Stack: Pushes 1 item: TOS = position (1-based from start, 0 if not found).

' =================================================================

' --- Initialize Pass/Fail counters ---

$$PAS=0

$$FAI=0

STS.CLEAR

PRT. ===================================================

PRT. 1. FORWARD SEARCH TESTS (P3 > 0)

PRT. ===================================================

$$SRC=HelloWorldHello

PRT. Test 1.1: Forward 1st "Hello" (P3=1)...

STR.XInstr|$$SRC|Hello|1|1

POP.$$POS

$$EXP=1

IVV.$$POS=$$EXP

 PRT. -> PASS

 VIC.$$PAS

ELS.

 $$MSG= -> FAIL - Expected: $$EXP, Actual: $$POS

 PRT.$$MSG

 VIC.$$FAI

EIF.

STS.CLEAR

 

PRT. Test 1.2: Forward 2nd "Hello" (P3=2)...

STR.XInstr|$$SRC|Hello|2|1

POP.$$POS

$$EXP=11

IVV.$$POS=$$EXP

 PRT. -> PASS

 VIC.$$PAS

ELS.

 $$MSG= -> FAIL - Expected: $$EXP, Actual: $$POS

 PRT.$$MSG

 VIC.$$FAI

EIF.

STS.CLEAR

 

PRT. Test 1.3: Forward with start position (P4=6)...

STR.XInstr|$$SRC|Hello|1|6

POP.$$POS

$$EXP=11

IVV.$$POS=$$EXP

 PRT. -> PASS (skips first "Hello")

 VIC.$$PAS

ELS.

 $$MSG= -> FAIL - Expected: $$EXP, Actual: $$POS

 PRT.$$MSG

 VIC.$$FAI

EIF.

STS.CLEAR

 

PRT. ===================================================

PRT. 2. REVERSE SEARCH TESTS (P3 < 0)

PRT. ===================================================

PRT. Test 2.1: Reverse 1st "Hello" (P3=-1)...

STR.XInstr|$$SRC|Hello|-1|-1

POP.$$POS

$$EXP=11

IVV.$$POS=$$EXP

 PRT. -> PASS

 VIC.$$PAS

ELS.

 $$MSG= -> FAIL - Expected: $$EXP, Actual: $$POS

 PRT.$$MSG

 VIC.$$FAI

EIF.

STS.CLEAR

 

PRT. Test 2.2: Reverse 2nd "Hello" (P3=-2)...

STR.XInstr|$$SRC|Hello|-2|-1

POP.$$POS

$$EXP=1

IVV.$$POS=$$EXP

 PRT. -> PASS

 VIC.$$PAS

ELS.

 $$MSG= -> FAIL - Expected: $$EXP, Actual: $$POS

 PRT.$$MSG

 VIC.$$FAI

EIF.

STS.CLEAR

 

PRT. Test 2.3: Reverse with start from end (P4=-5)...

' Start 5 chars from end in "HelloWorldHello" (len=15) ? pos=11

' Should find "Hello" at 11

STR.XInstr|$$SRC|Hello|-1|-5

POP.$$POS

$$EXP=1

IVV.$$POS=$$EXP

 PRT. -> PASS

 VIC.$$PAS

ELS.

 $$MSG= -> FAIL - Expected: $$EXP, Actual: $$POS

 PRT.$$MSG

 VIC.$$FAI

EIF.

STS.CLEAR

 

PRT. ===================================================

PRT. 3. OVERLAP TESTS

PRT. ===================================================

$$SRC=aaa

PRT. Test 3.1: Forward overlap (P5=1) — 2nd "aa" in "aaa"...

STR.XInstr|$$SRC|aa|2|1|1

POP.$$POS

$$EXP=2

IVV.$$POS=$$EXP

 PRT. -> PASS

 VIC.$$PAS

ELS.

 $$MSG= -> FAIL - Expected: $$EXP, Actual: $$POS

 PRT.$$MSG

 VIC.$$FAI

EIF.

STS.CLEAR

 

PRT. Test 3.2: Forward no overlap (P5=0) — 2nd "aa" not found...

STR.XInstr|$$SRC|aa|2|1|0

POP.$$POS

$$EXP=0

IVV.$$POS=$$EXP

 PRT. -> PASS

 VIC.$$PAS

ELS.

 $$MSG= -> FAIL - Expected: $$EXP, Actual: $$POS

 PRT.$$MSG

 VIC.$$FAI

EIF.

STS.CLEAR

 

PRT. Test 3.3: Reverse overlap — 2nd "aa" from end...

STR.XInstr|$$SRC|aa|-2|-1|1

POP.$$POS

$$EXP=0

IVV.$$POS=$$EXP

 PRT. -> PASS

 VIC.$$PAS

ELS.

 $$MSG= -> FAIL - Expected: $$EXP, Actual: $$POS

 PRT.$$MSG

 VIC.$$FAI

EIF.

STS.CLEAR

 

PRT. ===================================================

PRT. 4. EDGE CASE TESTS

PRT. ===================================================

PRT. Test 4.1: No match (forward)...

$$SRC=Hello

STR.XInstr|$$SRC|xyz|1|1

POP.$$POS

$$EXP=0

IVV.$$POS=$$EXP

 PRT. -> PASS

 VIC.$$PAS

ELS.

 $$MSG= -> FAIL - Expected: $$EXP, Actual: $$POS

 PRT.$$MSG

 VIC.$$FAI

EIF.

STS.CLEAR

 

PRT. Test 4.2: No match (reverse)...

STR.XInstr|$$SRC|xyz|-1|-1

POP.$$POS

$$EXP=0

IVV.$$POS=$$EXP

 PRT. -> PASS

 VIC.$$PAS

ELS.

 $$MSG= -> FAIL - Expected: $$EXP, Actual: $$POS

 PRT.$$MSG

 VIC.$$FAI

EIF.

STS.CLEAR

 

PRT. Test 4.3: Empty source...

$$SRC=

STR.XInstr|$$SRC|test|1|1

POP.$$POS

$$EXP=0

IVV.$$POS=$$EXP

 PRT. -> PASS

 VIC.$$PAS

ELS.

 $$MSG= -> FAIL - Expected: $$EXP, Actual: $$POS

 PRT.$$MSG

 VIC.$$FAI

EIF.

STS.CLEAR

 

PRT. Test 4.4: Empty search string...

STR.XInstr|Hello||1|1

POP.$$POS

$$EXP=0

IVV.$$POS=$$EXP

 PRT. -> PASS

 VIC.$$PAS

ELS.

 $$MSG= -> FAIL - Expected: $$EXP, Actual: $$POS

 PRT.$$MSG

 VIC.$$FAI

EIF.

STS.CLEAR

 

PRT. Test 4.5: Pattern longer than source...

STR.XInstr|Hi|Hello|1|1

POP.$$POS

$$EXP=0

IVV.$$POS=$$EXP

 PRT. -> PASS

 VIC.$$PAS

ELS.

 $$MSG= -> FAIL - Expected: $$EXP, Actual: $$POS

 PRT.$$MSG

 VIC.$$FAI

EIF.

STS.CLEAR

 

PRT. ===================================================

PRT. 5. BOUNDARY & SPECIAL CASES

PRT. ===================================================

PRT. Test 5.1: P4=0 defaults to 1 (forward)...

$$SRC=HelloWorld

STR.XInstr|$$SRC|o|2|0

POP.$$POS

$$EXP=7

IVV.$$POS=$$EXP

 PRT. -> PASS

 VIC.$$PAS

ELS.

 $$MSG= -> FAIL - Expected: $$EXP, Actual: $$POS

 PRT.$$MSG

 VIC.$$FAI

EIF.

STS.CLEAR

 

PRT. Test 5.2: P4=0 defaults to end (reverse)...

STR.XInstr|$$SRC|o|-2|0

POP.$$POS

$$EXP=5

IVV.$$POS=$$EXP

 PRT. -> PASS

 VIC.$$PAS

ELS.

 $$MSG= -> FAIL - Expected: $$EXP, Actual: $$POS

 PRT.$$MSG

 VIC.$$FAI

EIF.

STS.CLEAR

 

PRT. Test 5.3: Match at very end (forward)...

$$SRC=EndsWithHello

STR.XInstr|$$SRC|Hello|1|1

POP.$$POS

$$EXP=9

IVV.$$POS=$$EXP

 PRT. -> PASS

 VIC.$$PAS

ELS.

 $$MSG= -> FAIL - Expected: $$EXP, Actual: $$POS

 PRT.$$MSG

 VIC.$$FAI

EIF.

STS.CLEAR

 

PRT. Test 5.4: Match at very start (reverse)...

STR.XInstr|$$SRC|Ends|-1|-1

POP.$$POS

$$EXP=1

IVV.$$POS=$$EXP

 PRT. -> PASS

 VIC.$$PAS

ELS.

 $$MSG= -> FAIL - Expected: $$EXP, Actual: $$POS

 PRT.$$MSG

 VIC.$$FAI

EIF.

STS.CLEAR

 

PRT. Test 5.5: Negative P3 with positive P4 (should treat as reverse start)...

' P4=10 in reverse mode = start from 10th char from end

STR.XInstr|HelloWorldHello|Hello|-1|10

POP.$$POS

$$EXP=11

IVV.$$POS=$$EXP

 PRT. -> PASS

 VIC.$$PAS

ELS.

 $$MSG= -> FAIL - Expected: $$EXP, Actual: $$POS

 PRT.$$MSG

 VIC.$$FAI

EIF.

STS.CLEAR

 

PRT. ===================================================

PRT. TEST SUMMARY

PRT. ===================================================

CAL.$$TOT=$$PAS+$$FAI

$$MSG=Total Tests: $$TOT

PRT.$$MSG

$$MSG=Passed: $$PAS

PRT.$$MSG

$$MSG=Failed: $$FAI

PRT.$$MSG

' --- Display final result message box ---

IVV.$$FAI=0

 MBX.SUCCESS: All tests passed!|Test Result|64

ELS.

 $$MSG=FAILURE: $$FAI of $$TOT tests failed.

 MBX.$$MSG|Test Result|16

EIF.

ENR.

 

Remarks

 

-Case-sensitive search; "Hello" does not match "hello".

-P3 positive: counts left-to-right; negative: counts right-to-left.

-P4=0 defaults to 1 (LTR) or end (RTL based on P3 sign).

-P5=1 allows overlapping (e.g., "aa" in "aaa" finds 2); default 0 (non-overlapping).

-Result is always pushed to TOS, even if P6 is specified.

-If nth occurrence not found or search string longer than remaining source, returns 0.

-Binary-safe for P1 and P2; no special/system vars expanded.

-For case-insensitive search, use STR.CiInstr; for patterns, use STR.FindAny.

 

Limitations

 

-No wildcard or pattern support; use STR.FindAny for patterns.

-P3 must be non-zero; invalid values may cause undefined behavior.

-No reverse direction for positive P3; use negative P3/P4 for RTL counting.

 

See also:

STR.Instr

STR.CiInstr

STR.FindAny

STR.Contains

STR.CIContains

The Stack (TOS)