Unfortunately, as you are storing you tags within a string and not a more complex data structure (such as a custom class), you will need to test the individual string segments for the substring (in your case, "xx"). However, there are ways to make it more efficient.
Drawing from your question, the tag begins with Line, contains zero or more words, lists Source, contains zero or more words, and finishes with Target. Line, Source, and Target are all definites (they must appear in each tag). At this point, we can already rule out the first and last elements from the Source problem.
(At this point, I am being cautions, but you can modify my answer to make function better.) Source begins with some characters, contains the string "xx", and concludes with some more characters. This identifying characteristic allows us to iterate over the array and get the correct index.
string[] arr = s.Split("_");
int index = arr.Length - 2; // skip last item since that is Target
for (; index > 0; index--)
if (arr[index].Contains("xx"))
break;
From your example, I assumed that there would be more _word_s from in the first section, so I sent the search from back to front. If it is the other way, or you don't know, you can reverse the search. Once the element in the array containing the substring "xx" is identified, the loop terminates and the current index is stored. After that, you can use it as you wish.
Some further notes:
- You can compress the
for loop into one line with for (; index > 0 && !arr[index].Contains("xx"); index--); if you want a smaller footprint, but I'd recommend against it for readability.
- If many of the strings you are to test contain many extraneous words, and you know Source must always be a specific length (from your example, 6), testing the element's length (
.Length) before what it contains can shorten the search by some computer cycles. This is because the string's length is stored as a property and only requires a quick lookup, while .Contains is a function and must actually test the characters of the element, requiring multiple calculations. But this should only be added if there are a large number of those words; otherwise the .Length lookups will total as more expensive than just starting with .Contains.
- If Source always starts with certain characters (in your example, "FTxx") that include the "xx", use
.StartsWith instead of .Contains. This is because .StartsWith returns false as soon as the condition fails, while .Contains must check the entire string (minus the length of the testing substring) before it can return false.