Cris
Cris

Reputation: 141

How to find strings that contain a substring from a given list

I have a string that may or may not contain some specific words. IF it contain the one of the works I want to print the string in a different color (depending on the word) So I was thinking to have an array containing the list of the words (e.g. one for red word one for yellow and one for green as the example below:

push(@red_word, [ "error","ERROR","Assertion","assertion","Error","ASSERTION","Errors" ]);
push(@yellow_word, [ "WARNING","Warning","warning","PAUSED","Paused","paused","Warnings" ]);
push(@green_word, [ "ACTIVE","Active","active" ]);

$l is the string i want to check, I tried something like this

foreach my $l (@$lines) {
    if ($l =~ @red_word) {
            print '<FONT COLOR="FF0000">'.$l.'</FONT><br>';
    }
    else {
        if ($l =~ @yellow_word) {
            print '<FONT COLOR="FFFF00">'.$l.'</FONT><br>';
        }
        else {      
            if ($l =~ @green_word) {
                print '<FONT COLOR="008000">'.$l.'</FONT><br>';
            }
            else {
                print '<FONT COLOR="000000">'.$l.'</FONT><br>';
            }
        }
    }
}

but the result is erratic, some lines are printed in red without any relation to the list red_word.

what am I doing wrong?

Upvotes: 3

Views: 77

Answers (1)

Sobrique
Sobrique

Reputation: 53478

This isn't doing what you think it's doing:

push(@red_word, [ "error","ERROR","Assertion","assertion","Error","ASSERTION","Errors" ]);
push(@yellow_word, [ "WARNING","Warning","warning","PAUSED","Paused","paused","Warnings" ]);
push(@green_word, [ "ACTIVE","Active","active" ]);

You're creating a two dimensional data structure a single element array, containing a nested array.

$VAR1 = [
          [
            'error',
            'ERROR',
            'Assertion',
            'assertion',
            'Error',
            'ASSERTION',
            'Errors'
          ]
        ];

That match isn't going to work very well as a result. I'm not actually sure what it'll be doing, but it won't be testing 'if the word is in the list'.

Try instead building a regular expression from your array:

my @red_words = (
    "error", "ERROR",     "Assertion", "assertion",
    "Error", "ASSERTION", "Errors"
);
my $is_red = join( "|", map {quotemeta} @red_words );
$is_red = qr/($is_red)/;

print "Red" if $line =~ m/$is_red/;

Perhaps something like this:

#!/usr/bin/env perl

use strict;
use warnings;

my %colour_map = (
    'error'     => 'FF0000',
    'errors'    => 'FF0000',
    'assertion' => 'FF0000',
    'warning'   => 'FFFF00',
    'warnings'  => 'FFFF00',
    'paused'    => 'FFFF00',
    'active'    => '008000',
);

my $search = join( "|", map {quotemeta} keys %colour_map );
$search = qr/\b($search)\b/;

my @lines = (
    "line containing assertion",
    "a warning",
    "green for active",
    "A line containing ACTIVE"
);


foreach my $line (@lines) {
    if ( my ($word) = $line =~ m/$search/ ) {
        print "<FONT COLOR=\"$colour_map{lc($word)}\">$line</FONT><BR/>\n";
    }
    else {
        print "<FONT COLOUR=\"000000\">$line</FONT><BR/>\n";
    }
}

(Not entirely sure if there's a way to tranpose a list of matches. I'll have another think).

Upvotes: 4

Related Questions