manish.rathi has asked for the wisdom of the Perl Monks concerning the following question:

use File::Basename

print "filename : ";

chomp(my $old_name = <stdin>);

my $dirname = dirname $old_name ;

my $basename = basename $old_name ;

$basename =~ s/^/not/ ;

my $new_name = "$dirname/$basename" ;

rename($old_name, $new_name);

-----------------------------------------------------

I have some confusion in this syntax

1) when a variable is declared in the main block only, why do we neeed to make it local ? If a variable is declared local in the main block, does it mean that if a subroutine is declared then this variable can not be used inside subroutines as its declared outside the subroutine as local ?

2) my $dirname = dirname $old_name ; # what does this syntax mean ? I have used $num = @number, to find out the number of elements in an array. I have not used any kind of name before a variable name so far.

3) s/^/not/, # does it mean that not will be added at the start of the string ?

4) (my $basename = $name =~ s#./##; # how come there is only one forward slash ?

What is the meaning of this regex ? Whenever we want to substitute values, we do =~ s/something/this/g ; there are two forward slashes in the regex. What kind of regex is this ?

Replies are listed 'Best First'.
Re: Pls explain this syntax
by ikegami (Patriarch) on Feb 22, 2009 at 22:20 UTC

    when a variable is declared in the main block only, why do we neeed to make it local ?

    • To ensure it's only used in the "main block". In other words, it provides encapsulation.
    • To allow the program to run. It won't run if you don't (assuming you didn't unwisely disable strictures by omitting use strict;)

    If a variable is declared local in the main block, does it mean that if a subroutine is declared then this variable can not be used inside subroutines as its declared outside the subroutine as local ?

    It depends on the ordering, since the subroutines exist in the file's lexical scope (what you call "the main block").

    use strict; my $x; sub foo { $x = 'foo'; # Ok } foo(); print($x); # foo

    -vs-

    use strict; sub foo { $x = 'foo'; # Refers to package var $main::x. # It's also a compilation error. } my $x; foo(); print($x); # foo

    my $dirname = dirname $old_name ; # what does this syntax mean ?

    Call sub dirname with argument $old_name. Declare $dirname and assign the result of the call to dirname to it.

    s/^/not/, # does it mean that not will be added at the start of the string ?

    Yes. Why didn't you try it?

    /^/ in a regexp patterm means "the start of the string" (or "the start of the line" if the "m" modifier is used). So s/^/not/ means "replace the start of the string with 'not'" or in better English, "prepend 'not' to the string". It could have been written

    $basename = 'not' . $basename;

    (my $basename = $name =~ s#./##; # how come there is only one forward slash ?

    Why not?

    Though that's buggy for two reasons. There's a missing closing paren, and it should be s#.*/##s ("replace everything up to the last slash with nothing").

      I am still having confusion about my last question. We can use any delimiter / or #. s#^https://#http://# ; in this syntax # is used instead of /

      s#./##s; in this syntax, it looks that delimiter is #, but can we use different separator between two strings than the delimitor. It looks the separator is "/".

      Pls explain

        The character (space excepted) that immediately follows the "s" is the delimiter.

        It looks the separator is "/".

        No, it's "#", since that's the character that follows the "s". "./" is the pattern, "" is the replacement.

Re: Pls explain this syntax
by gwadej (Chaplain) on Feb 22, 2009 at 22:40 UTC

    Much of this can be understood by checking the relevant documentation.

    1) While you could declare these variables to be package variables (using our, or by using their full names, you don't really gain any benefit over declaring them as lexical variables with my.

    IMHO, the main reason for using my is to help develop good habits. When making a module, you might want to declare variables that are only available inside the module. You would use my for this. The only reason to use our would be if you wanted the variables to be accessible outside the module. Using my by default gets you in the habit of reducing the coupling between different parts of you code, unless you specifically choose otherwise.

    2) The dirname in this case is a function call (see File::Basename). This is not to be confused with $dirname which is a scalar variable. dirname has no more in common with $dirname than @dirname does. Using different names would have made this example a bit clearer.

    3) Yes.

    4) See the documentation for s/// (in Regexp Quote Like Operators) where you will find that the substitution operation (and the match operator m// both support alternate delimiters. In this case, the delimiter is #.

    G. Wade
Re: Pls explain this syntax
by zwon (Abbot) on Feb 22, 2009 at 22:24 UTC
    If a variable is declared local in the main block, does it mean that if a subroutine is declared then this variable can not be used inside subroutines as its declared outside the subroutine as local ?

    No, it doesn't. You can use variable in subroutine.

    my $dirname = dirname $old_name ; # what does this syntax mean ?

    This mean my $dirname = dirname($old_name);. (dirname is a function from File::Basename)

    does it mean that not will be added at the start of the string ?

    Correct

    (my $basename = $name =~ s#./##; # how come there is only one forward slash ?

    You can use any symbol as regexp delimiter. This is the same as $name =~ s/.\///

Re: Pls explain this syntax
by shmem (Chancellor) on Feb 22, 2009 at 23:25 UTC
    1) when a variable is declared in the main block only, why do we neeed to make it local ?

    Huh? I don't see the local keyword anywhere in the code you've posted. But see my/local, space/time (was: Re: The difference between my and local).

    2) my $dirname = dirname $old_name ; # what does this syntax mean ? I have used $num = @number, to find out the number of elements in an array. I have not used any kind of name before a variable name so far.

    dirname is a funtion defined inFile::Basename.

    3) s/^/not/, # does it mean that not will be added at the start of the string ?

    Yes.

    4) (my $basename = $name =~ s#./##; # how come there is only one forward slash ?

    s// can take any sensible delimiters. See perle, perlop and such.

    Read the documentation!

Re: Pls explain this syntax
by scorpio17 (Canon) on Feb 23, 2009 at 14:45 UTC

    Regarding this question:

    4) (my $basename = $name =~ s#./##; # how come there is only one forward slash ?

    You're allowed to use characters other than '/' as regex delimiters. This is usually done if the regex contains the '/' character. Otherwise you have to escape it with '\'. So, for your example, you can use either of these:

    (my $basename = $name =~ s#./##;
    (my $basename = $name =~ s/.\///;

    The notion being that all those backslash escapes make the regex less readable.