Difference between revisions of "LlSubStringIndex"

From Second Life Wiki
Jump to navigation Jump to search
m
m (added another example)
Line 13: Line 13:
* There is no function to search the string starting at a specific offset. check [[LlSubStringIndex#See_Also|See Also]] for a function to search from the end.
* There is no function to search the string starting at a specific offset. check [[LlSubStringIndex#See_Also|See Also]] for a function to search from the end.
|constants
|constants
|examples=Matching against last names:
|examples=
<lsl>
<lsl>
default
default
Line 19: Line 19:
     state_entry()
     state_entry()
     {
     {
         llSensorRepeat("", NULL_KEY, AGENT, PI, 96.0, 20);
    //  PUBLIC_CHANNEL has the integer value 0
 
         llSay(PUBLIC_CHANNEL, "Hello, Avatar!");
     }
     }
   
 
     sensor(integer NumDet)
     touch_start(integer num_detected)
     {
     {
         integer i;
        key id = llDetectedKey(0);
          
        string name = llKey2Name(id);
         //Loop through all the sensor data and match against " Linden",  
         integer spaceIndex = llSubStringIndex(name, " ");
        //this causes it to match with any last name of Linden (since there can't be spaces before the firstname)
         string firstName = llGetSubString(name, 0, spaceIndex - 1);
        //Alternatively you could match a firstname with "FirstName "
 
         for(i = 0; i < NumDet; ++i)
         llSay(PUBLIC_CHANNEL, firstName + " touched me.");
             if(~llSubStringIndex(llDetectedName(i), " Linden"))
    }
                 llInstantMessage(llDetectedKey(i), "Hello, I see you!");
}
</lsl>
<lsl>
default
{
    state_entry()
    {
        llSensorRepeat("", NULL_KEY, AGENT_BY_LEGACY_NAME, PI, 96.0, 20);
    }
 
    sensor(integer num_detected)
    {
    /Loop through all the sensor data and match against " Linden",  
    // this causes it to match with any last name of Linden (since there can't be spaces before the firstname)
    // Alternatively you could match a firstname with "FirstName " or anything else
 
        integer index;
        do
        {
            key avatarKey = llDetectedKey(index);
            string avatarLegacyName = llDetectedName(index);
 
         //  watch out for the bitwise-NOT (~)
        //  the next line translates to if (0 <= indexOfSearchedStringInOtherString)
             integer isReallyALinden = ~llSubStringIndex(avatarLegacyName, " Linden");
 
            if (isReallyALinden)
                 llInstantMessage(avatarKey, "Hello, I see you!");
        }
        while (++index < num_detected);
     }
     }
}
}

Revision as of 13:06, 7 November 2012

Summary

Function: integer llSubStringIndex( string source, string pattern );
0.0 Forced Delay
10.0 Energy

Returns an integer that is the index of the first instance of pattern in source.

• string source
• string pattern

If pattern is not found in source, -1 is returned.
The index of the first character in the string is 0

Caveats

  • Performs a literal match (case sensitive).
    • Wildcards and RegEx are not supported.
  • if (pattern == ""), return = 0, instead of -1.
  • There is no function to search the string starting at a specific offset. check See Also for a function to search from the end.

Examples

<lsl> default {

   state_entry()
   {
   //  PUBLIC_CHANNEL has the integer value 0
       llSay(PUBLIC_CHANNEL, "Hello, Avatar!");
   }
   touch_start(integer num_detected)
   {
       key id = llDetectedKey(0);
       string name = llKey2Name(id);
       integer spaceIndex = llSubStringIndex(name, " ");
       string firstName = llGetSubString(name, 0, spaceIndex - 1);
       llSay(PUBLIC_CHANNEL, firstName + " touched me.");
   }

} </lsl> <lsl> default {

   state_entry()
   {
       llSensorRepeat("", NULL_KEY, AGENT_BY_LEGACY_NAME, PI, 96.0, 20);
   }
   sensor(integer num_detected)
   {
   //  Loop through all the sensor data and match against " Linden", 
   //  this causes it to match with any last name of Linden (since there can't be spaces before the firstname)
   //  Alternatively you could match a firstname with "FirstName " or anything else
       integer index;
       do
       {
           key avatarKey = llDetectedKey(index);
           string avatarLegacyName = llDetectedName(index);
       //  watch out for the bitwise-NOT (~)
       //  the next line translates to if (0 <= indexOfSearchedStringInOtherString)
           integer isReallyALinden = ~llSubStringIndex(avatarLegacyName, " Linden");
           if (isReallyALinden)
               llInstantMessage(avatarKey, "Hello, I see you!");
       }
       while (++index < num_detected);
   }

} </lsl>

Basic Example: <lsl>integer index = llSubStringIndex("string data","TEST"); if(index == -1) {

   llSay(0,"TEST was not found in the string");

} else {

   llSay(0,"TEST was found in the string.");

}</lsl>

String Cheese

<lsl>//This example shows how you can ask if a word or group of words is in a given string. //There is a limitation with this function. Your search of the string is for an exact match (case sensitive) //so the string_example below would be hard to match.

string string_example = "ThIs serVes As aN exaMplE sTrinG. It ISn't toO coMPleX bUt HaS sOme mIlD vARietY";

//If you chat a question "Search for search_word" within range of the object this script is in //it will recognize (by searching the chat msg) the "search for" part and take the word or words following it //and check the string_example for those words.

string search_test_a = "seArCh foR";

//The example below works the same way but searches for the word in front of the recognized trigger question.

string search_test_b = "is the word I seek";

//Using this variable provides a way to manipulate the word(s) during the script without damaging the msg.

string search_word;

default {

   on_rez(integer param)//Although reseting the script on_rez provides many benefits
   { //in some cases it would be a bad idea because stored variables, lists and queued events would be trashed.
       llResetScript();
   }
   state_entry()
   {   //This is just for fun (but better to know what object is talking to you).
       llSetObjectName("String Cheese");
       llListen(0, "", llGetOwner(), "");//Listen to you on the public chat channel for everything you say.
   }
   listen(integer chan, string name, key id, string msg)
   {
       if(llSubStringIndex(llToUpper(msg), llToUpper(search_test_a)) != -1)
       {
           search_word = llStringTrim(llGetSubString(msg, llStringLength(search_test_a), -1), STRING_TRIM);
           if(llSubStringIndex(llToUpper(string_example), llToUpper(search_word)) != -1)
           {
               llSay(0, "I have found the word " + "" + search_word + "" + " in the example string");
           }
           else                         
           {
               llSay(0, "I cannot find the word " + "" + search_word + "" + " in the example string.");
           }
       }
       if(llSubStringIndex(msg, search_test_b) != -1)
       {
           search_word = llStringTrim(llGetSubString(msg, 0, (llSubStringIndex(msg, search_test_b)-1)), STRING_TRIM);
           if(llSubStringIndex(string_example, search_word) != -1)
           {
               llSay(0, "I have found the word " + "" + search_word + "" + " in the example string");
           }
           else
           {
               llSay(0, "I cannot find the word " + "" + search_word + "" + " in the example string.");
           }
       }
   }
}</lsl>

Useful Snippets

Tests to see if one string contains a copy of another:

1. Concise & conventional:

<lsl> integer contains(string haystack, string needle) // http://wiki.secondlife.com/wiki/llSubStringIndex {

   return 0 <= llSubStringIndex(haystack, needle);

} </lsl>

<lsl>integer startswith(string haystack, string needle) // http://wiki.secondlife.com/wiki/llSubStringIndex {

   return llDeleteSubString(haystack, llStringLength(needle), -1) == needle;

}</lsl>

<lsl>integer endswith(string haystack, string needle) // http://wiki.secondlife.com/wiki/llSubStringIndex {

   return llDeleteSubString(haystack, 0, ~llStringLength(needle)) == needle;

}</lsl>

Note: Some of the snippets above return a result without ever calling llSubStringIndex.

2. Clever & smaller (calculates contains in ~54 bytes rather than ~60):

<lsl>integer contains(string haystack, string needle) // http://wiki.secondlife.com/wiki/llSubStringIndex {

   return ~llSubStringIndex(haystack, needle);

}</lsl>

Note: The llSubStringIndex function returns -1 only when not found and the ~ operator returns zero only for -1, so the clever combination ~llSubStringIndex returns zero only for not found, else nonzero for found.

Note: Smaller was not noticeably faster or slower when our Code Racer and Efficiency Tester harnesses measured the expression { contains("wiki.secondlife.com", "wiki"); }.

See Also

Functions

•  llListFindList Find a list in another list
•  llGetSubString Copy out part of a string of characters
•  uSubStringLastIndex Returns an integer that is the index of the last pattern in source.

Deep Notes

Signature

function integer llSubStringIndex( string source, string pattern );