Option Compare Binary Option Explicit On Option Infer On Option Strict On Public Class StringIndex Private Const NOT_FOUND = -1 Private _where As String Private _what As String Private _index As Integer Public Sub New(ByVal where As String, ByVal what As String, Optional ByVal index As Integer = NOT_FOUND) _index = index _where = where _what = what End Sub Private Function Validate(ByVal name As String, ByVal value As Integer) As Integer If value < 0 Then Throw New Exception($"[{value}] cannot be negative!") Return value End Function Public ReadOnly Property Found() As Boolean Get Return _index <> NOT_FOUND End Get End Property Public ReadOnly Property What() As String Get If _index = NOT_FOUND Then Return String.Empty Return _where.Substring(_index, _what.Length) End Get End Property Public Function Before() As String If _index = NOT_FOUND Then Return String.Empty Return _where.Substring(0, _index) End Function Public Function After() As String If _index = NOT_FOUND Then Return String.Empty Dim start = _what.Length + _index If start >= _where.Length Then Return String.Empty Return _where.Substring(start) End Function Public Function TakeBackward(ByVal count As Integer, Optional ByVal skip As Integer = 0) As String count = Validate("count", count) skip = Validate("skip", skip) If count = 0 OrElse _index = NOT_FOUND Then Return String.Empty Dim start = _index - count - skip If start < 0 Then start = 0 count = _index - start - skip If count <= 0 Then Return String.Empty If start + count >= _where.Length Then count = _where.Length - start Return _where.Substring(start, count) End Function Public Function TakeForward(ByVal count As Integer, Optional ByVal skip As Integer = 0) As String count = Validate("count", count) skip = Validate("skip", skip) If count = 0 OrElse _index = NOT_FOUND Then Return String.Empty Dim start = _index + _what.Length + skip If start >= _where.Length Then Return String.Empty If start + count >= _where.Length Then count = _where.Length - start Return _where.Substring(start, count) End Function Public Shared Operator IsTrue(obj As StringIndex) As Boolean Return obj.Found End Operator Public Shared Operator IsFalse(obj As StringIndex) As Boolean Return Not obj.Found End Operator End Class Public Class StringFinder Public Shared Function Find(ByVal where As String, ByVal what As String, Optional ByVal caseInsensitive As Boolean = False) As StringIndex If String.IsNullOrEmpty(where) OrElse String.IsNullOrEmpty(what) Then Return New StringIndex(String.Empty, String.Empty) Dim index As Integer If caseInsensitive Then index = where.IndexOf(what, StringComparison.CurrentCultureIgnoreCase) Else index = where.IndexOf(what) End If If index = -1 Then Return New StringIndex(where, what) Return New StringIndex(where, what, index) End Function Public Shared Function Between( ByVal where As String, ByVal left As String, ByVal right As String, Optional ByVal caseInsensitive As Boolean = False ) As StringIndex Dim first = Find(where, left, caseInsensitive) If Not first.Found Then Return first Dim second = Find(first.After(), right, caseInsensitive) If Not second.Found Then Return first Return Find(where, left & second.Before() & right, caseInsensitive) End Function End Class Module Module1 Sub Main() Const txt = "The brown fox jumped over the lazy dog" Dim found = StringFinder.Find(txt, "FOX", caseInsensitive:=True) If found Then Console.WriteLine("->" & found.Before() & "<-") Console.WriteLine("->" & found.After() & "<-") Console.WriteLine("->" & found.TakeBackward(count:=4, skip:=1) & "<-") Console.WriteLine("->" & found.TakeForward(count:=6, skip:=1) & "<-") Console.WriteLine("->" & found.What & "<-") Else Console.WriteLine("Not found!") End If found = StringFinder.Between(txt, "brown", "jumped") Console.WriteLine("->" & found.Before() & "<-") Console.WriteLine("->" & found.After() & "<-") Console.WriteLine("->" & found.What & "<-") End Sub End Module