Perl: print the name of the input file

The special variable $ARGV could be used to get the name of the input file.
It returns the name of the file or ‘-‘ if the standard input was used.

Here are some examples:


perl -nle 'END { print $ARGV }' /etc/passwd
/etc/passwd


echo test | perl -nle 'print $ARGV'
-


$ (echo test; echo test2) | perl -nle 'print $ARGV'
-
-


perl -nle 'print $ARGV if !$seen{$ARGV}++' /etc/passwd /etc/shells
/etc/passwd
/etc/shells

Perl: how to get the position of the match

Let’s search for the word “brave” in the string “Hello, new brave world!”.
There are several methods to get the position of the match in Perl.

#1 – use POS function
Function pos returns the position, where search was finished.


$txt = "Hello, brave new world!" ;
$txt =~ m/(brave)/g;
my $pos = pos($txt) - length $1;

#2 – use $PREMATCH variable
$PREMATCH varialbe (short name $`) contains the string, preceeding the match.
This method is easy, however it could significantly affect performance of other regular expressions (see RegExp book for the detailed explanation). Therefor, it’s not the best solution.


use English ;
$txt = "Hello, brave new world!" ;
$txt =~ m/(brave)/g;

###my $pos = length $`
my $pos = length $PREMATCH;

#3 – use @LAST_MATCH_START variable
This method was introduced in Perl 5.6.0 and it does not make any bad impact on performance – so it’s recommended solution.


use English qw( -no_match_vars );
$txt = "Hello, brave new world!" ;
$txt =~ m/(brave)/g;

### $pos = $-[0];
$pos = $LAST_MATCH_START[0];

Perl: SOAP problem with dateTime

The following error message was received by Perl application:
Unrecognized type ‘{http://www.w3.org/1999/XMLSchema}dateTime

The problem is caused by “dateTime” type: it was not supported in the 1999 XML Specification.
The solution is to switch to 2001 schema:

[cc lang=”Perl”]
my $soap = SOAP::Lite->uri( $NAMESPACE )->proxy( $PROXY_URL )->xmlschema (‘2001’);
[/cc]

Perl: Soap deserialization error

Sometimes the following error is displayed, if application uses the old version of CPAN SOAP module:
“Client Application failed during request deserialization: no element found at line 1, column 0, byte -1 at XML/Parser.pm”

The possilbe solution is to change SOAP::Transport::HTTP module (SOAP/Transport/HTTP.pm), function “handle”:

[cc lang=”perl”]
sysread( STDIN, $buffer, $length )
[/cc]

should be replaced by

[cc lang=”perl”]
read( STDIN, $buffer, $length )
[/cc]

Calculating the date of Easter

The easiest way is to use specialized package (like Date::Calc).
If You need standalone function, the following method could be used.


#!/usr/bin/perl

$year=$ARGV[ 0 ];
$isJulian=(defined($ARGV[ 1 ]) && $ARGV[ 1 ] eq 'julian');
$isOrthodox=(defined($ARGV[ 1 ]) && $ARGV[ 1 ] eq 'orthodox');

my ( $G , $C , $H, $I, $J , $L );

$G = $year % 19 ;
if ( $isJulian || $isOrthodox ) {
print ( $isJulian ? "Julian:" : "Orthodox:" );
$I = ( 19*$G + 15) % 30 ;
$J = ( $year + int($year/4) + $I) % 7 ;
}else{
print "Gregorian:" ;
$C = int( $year/100 );
$H = ($C - int($C/4) - int((8*$C+13)/25) + 19*$G + 15) % 30 ;
$I = $H - int($H/28)*(1 - int($H/28)*int(29/($H + 1))*int((21 - $G)/11)) ;
$J = ($year + int($year/4) + $I + 2 - $C + int($C/4) ) % 7 ;
}
$L = $I - $J ;
$EasterMonth = 3 + int(($L + 40)/44) ;
$EasterDay = $L + 28 - 31*int($EasterMonth/4) ;

if ( $isOrthodox ) {
( $EasterDay, $EasterMonth, $year ) = EasterOrthodox( $EasterDay, $EasterMonth, $year )
}

printf("Day=%d Mon=%d Year=%d \n", $EasterDay, $EasterMonth, $year );

sub EasterOrthodox
{
my ($pDay, $pMonth, $pYear) = @_ ;
my ( $extra , $tmp ) = ( 0, 0 );
my ( $rezDay, $rezMonth) = ( 0, 0 );

if (($pYear > 1582) && ($pYear <= 4099)) { $extra = 10; if ($pYear > 1600) {
$tmp = int($pYear/100) - 16;
$extra = $extra + $tmp - int($tmp/4);
}

$rezDay = $pDay + $extra;
$rezMonth = $pMonth;

if (($rezMonth == 3) && ($rezDay > 31)) {
$rezMonth = 4;
$rezDay = $rezDay - 31;
}

if (($rezMonth == 4) && ($rezDay > 30)) {
$rezMonth = 5;
$rezDay = $rezDay - 30;
}
}
return ( $rezDay, $rezMonth, $pYear )
}

Examples:
perl -w 2006
perl -w 2006 orthodox