134

How can I check whether a given string contains a certain substring, using Perl?

More specifically, I want to see whether s1.domain.example is present in the given string variable.

Stephen Ostermiller
  • 23,933
  • 14
  • 88
  • 109
Belgin Fish
  • 19,187
  • 41
  • 102
  • 131

3 Answers3

259

To find out if a string contains substring you can use the index function:

if (index($str, $substr) != -1) {
    print "$str contains $substr\n";
} 

It will return the position of the first occurrence of $substr in $str, or -1 if the substring is not found.

Eugene Yarmash
  • 142,882
  • 41
  • 325
  • 378
  • 8
    This way is especially preferrable, when you are searching using a variable - this way you won't have to double-escape characters (in this variable string), that are special for regular expressions (like `:`). – evgeny9 Apr 02 '13 at 14:10
  • See this as well - http://www.troubleshooters.com/codecorn/littperl/perlreg.htm – Sam B Dec 07 '20 at 19:45
67

Another possibility is to use regular expressions which is what Perl is famous for:

if ($mystring =~ /s1\.domain\.example/) {
   print qq("$mystring" contains "s1.domain.example"\n);
}

The backslashes are needed because a . can match any character. You can get around this by using the \Q and \E operators.

my $substring = "s1.domain.example";
    if ($mystring =~ /\Q$substring\E/) {
   print qq("$mystring" contains "$substring"\n);
}

Or, you can do as eugene y stated and use the index function. Just a word of warning: Index returns a -1 when it can't find a match instead of an undef or 0.

Thus, this is an error:

my $substring = "s1.domain.example";
if (not index($mystring, $substr)) {
    print qq("$mystring" doesn't contains "$substring"\n";
}

This will be wrong if s1.domain.example is at the beginning of your string. I've personally been burned on this more than once.

Stephen Ostermiller
  • 23,933
  • 14
  • 88
  • 109
David W.
  • 105,218
  • 39
  • 216
  • 337
  • I suppose `index()` is faster than regexps in the simple case? – G. Cito Feb 25 '16 at 00:16
  • 1
    An attempted perl answer to a question about [removing substrings](http://stackoverflow.com/a/35593275/2019415) - I did not compare speed but `=~`, `index()`, `~~` and [`match::simple`](https://metacpan.org/pod/match::simple) all seemed a bit `awk`-ward ... :-\ – G. Cito Feb 25 '16 at 00:20
  • You also have to make sure that the strings that you are comparing is not case sensitive. S1.DOMAIN.COM will not work for substring. But if you lc($givendomain), and then compare that with "s1.domain.com", then that will work. Also, substring is not necessarily the right approach - see my note above to eugene y's response – BlueChips23 Nov 10 '16 at 20:51
  • @David W. Somehow I can't get `domain.com` to match `subdomain.domain.com` using the REGEX above, any ideas ? – avrono Nov 15 '16 at 11:05
16

Case Insensitive Substring Example

This is an extension of Eugene's answer, which converts the strings to lower case before checking for the substring:

if (index(lc($str), lc($substr)) != -1) {
    print "$str contains $substr\n";
} 
James Oravec
  • 19,579
  • 27
  • 94
  • 160
  • 3
    Note that [`fc`](https://perldoc.pl/functions/fc) is recommended over `lc` for case-insensitive comparisons. – melpomene Sep 02 '19 at 11:11