rollsch
rollsch

Reputation: 2770

How to write a simple sub in perl that takes a string and returns a string?

sub getHeading
{
    my $var = $_[0];
    my $match;
     if ($match = ($var =~ m/$fivetonine/))
     {
        return "=";
     }
     if ($match = ($var =~ m/$tentofourteen/))
     {
        return "==";
     }
     if ($match = ($var =~ m/$fifteentonineteen/)){
        return "===";
     }
     return "===";
}
my $ref_to_getHeading = \getHeading;

and I am calling it via:

$html =~ s/(.*)<font size="([^"]+)">(.+)<\/font>(.*)/$ref_to_getHeading($2)$1$3$4$ref_to_getHeading($2)/m;

I am wanting to pass a string in to this function, I want to check if it is one of 3 different matches and return the appropriate number of = signs, I am doing this wrong but I can't figure out how to make it take parameters? I get a run time error saying $var is initialised? I tried using @_ but I don't really understand what the difference is.

Any help much appreciated, I have never written perl before and this is my first real program.

Upvotes: 0

Views: 188

Answers (2)

Hugmeir
Hugmeir

Reputation: 1259

Double mistake there.

First, you aren't taking a reference to a function - You need to add the ampersand.

But even if you do that, it won't work. You are missing the /e flag in your substitution: You can't dereference a coderef within a string like you'd normally do with (scalar|hash|array)ref:

my $example = sub { return "hello" };
say "$example->()"; #Will stringify the coderef.

You either need the /e flag,

$html =~ s/etc/$ref_to_getHeading->($2) . "$1$3$4" . $ref_to_getHeading->($2)/em;

Or a little trick:

$html =~ s/etc/@{[$ref_to_getHeading->($2)]}$1$3$4@{[$ref_to_getHeading->($2)]}/m;

EDIT: Gosh, am I a slow typist.. Anyhow, with either way, you should be able to call the sub directly, so no need for the coderef.

Upvotes: 3

Eric Strom
Eric Strom

Reputation: 40142

The line my $ref_to_getHeading = \getHeading; doesn't do what you think it does. To take a reference to a subroutine:

my $ref_to_getHeading = \&getHeading;  # note the &

So you were actually calling getHeading and storing the result. Since you passed no arguments, you got the undefined value warning.

The substitution however will never call the coderef, for that to happen, you need to add the e modifier to run the replacement text through eval:

$html =~ s/.../join '' => getHeading($2), $1, $3, $4, getHeading($2)/me;

you may run into issues here with getHeading resetting the match vars too early. In which case, try writing it this way:

$html =~ s{...}{
    my $body = $1 . $3 . $4;
    my $heading = getHeading($2);
    $heading . $body . $heading
}me;

The bracket change for s/// was not necessary, I just find it easier to read a multi-line curly block.

Upvotes: 3

Related Questions