127

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

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

Adexe Rivera
  • 404
  • 7
  • 12
Belgin Fish
  • 17,849
  • 40
  • 101
  • 129

3 Answers3

252

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
  • 131,677
  • 37
  • 301
  • 358
  • 7
    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
64

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

if ($mystring =~ /s1\.domain\.com/) {
   print qq("$mystring" contains "s1.domain.com"\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.com";
    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.com";
if (not index($mystring, $substr)) {
    print qq("$mystring" doesn't contains "$substring"\n";
} 

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

Community
  • 1
  • 1
David W.
  • 102,141
  • 38
  • 210
  • 325
  • 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
15

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
  • 18,191
  • 26
  • 87
  • 152
  • 3
    Note that [`fc`](https://perldoc.pl/functions/fc) is recommended over `lc` for case-insensitive comparisons. – melpomene Sep 02 '19 at 11:11