Welcome To Fedon Kadifeli’s Web Site HTML5 Powered


About Fedon Kadifeli Who Am I?


Useful Stuff Useful Stuff


Interesting StuffInteresting Stuff


Bogazici University Computer Engineering Bogaziçi Univ. CmpE


WWW Related Work WWW Related Work


WAP Related Work WAP Related Work


Searching My Pages Searching My Pages


Contacting Me Contacting Me

Click to open the original file perlscr.htm in a new window.

Some Useful Perl Scripts


Below I give some of my Perl scripts which may prove useful to you. If you have any questions, please feel free to mail me. Generally these scripts will run both on UNIX and Windows environments.


DAYLIGHT SAVING TIME CHECK

This script can be used to test and find the exact time your system's local time will change from normal time to daylight saving time and vice versa. The script takes two parameters: The first one indicates the starting time, the second one indicates the ending time of the test period. Appropriate default values will be used if no parameter is given. Times are in seconds starting from January 1, 1970 (UTC).

#!/usr/bin/perl
# dstcheck.pl - Test daylight saving time changes.
# Fedon Kadifeli, October 1998 - March 2012.

$usage='dstcheck.pl startsec endsec';
$date='08/03/2012 11:55';
$version='0.06';

die "Usage: $usage\n" if $#ARGV != 1 && $#ARGV != -1;
$startsec = $ARGV[0];
$startsec = 733_276_801 if $startsec eq "";
$endsec = $ARGV[1];
$endsec = 1_500_000_000 if $endsec eq "";
@abbr = qw( Sun Mon Tue Wed Thu Fri Sat );

$diff = 9999;
print " Testing seconds from $startsec to $endsec...\n";
for ($t=$startsec; $t<=$endsec; $t+=3600) {
  ($sec1,$min1,$hour1,$mday1,$mon1,$year1,$wday1) = localtime($t);
  ($sec2,$min2,$hour2,$mday2,$mon2,$year2,$wday2) = gmtime($t);
  $diff2 = $hour1 - $hour2;
  $diff2 += 24 if $diff2 < 0;
  if ($diff != $diff2) {
    $diff = $diff2;
    $plus = ($diff >= 0) ? "+" : "";
    $st = sprintf ("%d/%02d/%02d %s %02d:%02d:%02d",
      $year1+1900, $mon1+1, $mday1, $abbr[$wday1], $hour1, $min1, $sec1);
    $st .= sprintf (" [%d/%02d/%02d %s %02d:%02d:%02d UTC]",
      $year2+1900, $mon2+1, $mday2, $abbr[$wday2], $hour2, $min2, $sec2);
    print "$st $plus$diff - Seconds: $t\n";
  }
}

If you run this script using the command:

perl dstcheck.pl 1174784401 1600000000

It should display something like:

 Testing seconds from 1174784401 to 1600000000...
2007/03/25 Sun 04:00:01 [2007/03/25 Sun 01:00:01 UTC] +3 - Seconds: 1174784401
2007/10/28 Sun 03:00:01 [2007/10/28 Sun 01:00:01 UTC] +2 - Seconds: 1193533201
2008/03/30 Sun 04:00:01 [2008/03/30 Sun 01:00:01 UTC] +3 - Seconds: 1206838801
2008/10/26 Sun 03:00:01 [2008/10/26 Sun 01:00:01 UTC] +2 - Seconds: 1224982801
2009/03/29 Sun 04:00:01 [2009/03/29 Sun 01:00:01 UTC] +3 - Seconds: 1238288401
2009/10/25 Sun 03:00:01 [2009/10/25 Sun 01:00:01 UTC] +2 - Seconds: 1256432401
2010/03/28 Sun 04:00:01 [2010/03/28 Sun 01:00:01 UTC] +3 - Seconds: 1269738001
2010/10/31 Sun 03:00:01 [2010/10/31 Sun 01:00:01 UTC] +2 - Seconds: 1288486801
2011/03/28 Mon 04:00:01 [2011/03/28 Mon 01:00:01 UTC] +3 - Seconds: 1301274001
2011/10/30 Sun 03:00:01 [2011/10/30 Sun 01:00:01 UTC] +2 - Seconds: 1319936401
2012/03/25 Sun 04:00:01 [2012/03/25 Sun 01:00:01 UTC] +3 - Seconds: 1332637201
2012/10/28 Sun 03:00:01 [2012/10/28 Sun 01:00:01 UTC] +2 - Seconds: 1351386001
2013/03/31 Sun 04:00:01 [2013/03/31 Sun 01:00:01 UTC] +3 - Seconds: 1364691601
2013/10/27 Sun 03:00:01 [2013/10/27 Sun 01:00:01 UTC] +2 - Seconds: 1382835601
2014/03/31 Mon 04:00:01 [2014/03/31 Mon 01:00:01 UTC] +3 - Seconds: 1396227601
2014/10/26 Sun 03:00:01 [2014/10/26 Sun 01:00:01 UTC] +2 - Seconds: 1414285201
2015/03/29 Sun 04:00:01 [2015/03/29 Sun 01:00:01 UTC] +3 - Seconds: 1427590801
2015/10/25 Sun 03:00:01 [2015/10/25 Sun 01:00:01 UTC] +2 - Seconds: 1445734801
2016/03/27 Sun 04:00:01 [2016/03/27 Sun 01:00:01 UTC] +3 - Seconds: 1459040401
2016/10/30 Sun 03:00:01 [2016/10/30 Sun 01:00:01 UTC] +2 - Seconds: 1477789201
2017/03/26 Sun 04:00:01 [2017/03/26 Sun 01:00:01 UTC] +3 - Seconds: 1490490001
2017/10/29 Sun 03:00:01 [2017/10/29 Sun 01:00:01 UTC] +2 - Seconds: 1509238801
2018/03/25 Sun 04:00:01 [2018/03/25 Sun 01:00:01 UTC] +3 - Seconds: 1521939601
2018/10/28 Sun 03:00:01 [2018/10/28 Sun 01:00:01 UTC] +2 - Seconds: 1540688401
2019/03/31 Sun 04:00:01 [2019/03/31 Sun 01:00:01 UTC] +3 - Seconds: 1553994001
2019/10/27 Sun 03:00:01 [2019/10/27 Sun 01:00:01 UTC] +2 - Seconds: 1572138001
2020/03/29 Sun 04:00:01 [2020/03/29 Sun 01:00:01 UTC] +3 - Seconds: 1585443601

The output depends on the time zone of your system or environment. The above example is for “Europe/Istanbul” (i.e., roughly EET/EEST or GMT+02:00). It may be different for your environment. The first column indicates the local time, the second column indicates the GMT (or UTC) time. The third column indicates the difference of your local time from UTC. In the above example, you see that your system will switch to UTC+3 at 2019/03/31 Sun 04:00:01 local time and back to UTC+2 at 2019/10/27 Sun 03:00:01.


CALENDAR

This script is similar to the UNIX cal command. It will display a calendar for the current or any given month. It takes two parameters: The first one is the month (1..12) and the second one is the year (four digits). If no parameter is given, the calendar for the current month is displayed. This script is only for Gregorian calendars.

#!/usr/bin/perl
# cal.pl - Display the calendar of a given month.
# Fedon Kadifeli, 1998 - April 2003.

use integer;

%mon_ord = (
 "jan" => 1,  "feb" => 2,  "mar" => 3,  "apr" => 4,
 "may" => 5,  "jun" => 6,  "jul" => 7,  "aug" => 8,
 "sep" => 9,  "oct" => 10, "nov" => 11, "dec" => 12,
);
@monames = ("",
  " January", " February",   "  March",   "  April",
    "   May",    "  June",    "  July",  "  August",
 "September",  " October", " November", " December"
);
@monlens = (0,31,28,31,30,31,30,31,31,30,31,30,31);

die "Usage: cal.pl [month] [year]\n" if $#ARGV > 1;

($t,$t,$t,$t,$mon1,$year1,$t,$t,$t) = localtime(time);
$mon = (defined $ARGV[0]) ? $ARGV[0] : $mon1+1;
if ($mon =~ /^ *\d{1,2} *$/) {
  die "Month must be between 1 and 12!\n" unless ($mon>=1 && $mon<=12);
} else {
  $mon = $mon_ord{lc(substr($mon,0,3))};
  die "Wrong month name: $ARGV[0]!\n" unless defined($mon);
}
$year = (defined $ARGV[1]) ? $ARGV[1] : $year1+1900;
die "Wrong year: $year!\n" unless $year =~ /^ *\d{4} *$/;
$year = int($year);
die "Year must be greater than 0!\n" unless $year>0;
print "\n\t$monames[$mon] $year\n\nSun  Mon  Tue  Wed  Thu  Fri  Sat\n";
$monlens[2] = 29 if ($year%400==0) || (($year%4==0) && ($year%100!=0));
--$year;
$st = 1 + $year*365 + $year/4 - $year/100 + $year/400;
for ($i=1; $i<$mon; ++$i) {
  $st += $monlens[$i];
}
$st %= 7;
for ($i=0; $i<$st; ++$i) {
  print "     ";
}
for ($i=1; $i<=$monlens[$mon]; ++$i) {
  printf "%3d  ", $i;
  print "\n" if ($st+$i)%7==0;
}
print "\n\n";

If you run this script using the command:

perl cal.pl 1 1965

It should display something like:

         January 1965

Sun  Mon  Tue  Wed  Thu  Fri  Sat
                           1    2
  3    4    5    6    7    8    9
 10   11   12   13   14   15   16
 17   18   19   20   21   22   23
 24   25   26   27   28   29   30
 31

GREP

This script is a simple version of the UNIX grep command and is similar to the Windows find command. It will search lines in files for a specific regular expression. The standard UNIX grep switches (-i: ignore case; -v: display not matching lines) are supported.

#!/usr/bin/perl
# grep.pl - Simulate UNIX grep command.
# Fedon Kadifeli, 1998 - April 2003.

$opt = shift;
if ($opt =~ s/^\-//) {
  $re = shift;
} else {
  $re = $opt;
  $opt = "";
}
die "Usage: grep.pl [-iv] regexp [files]\n" if ! defined $re;
$igncase = ($opt =~ s/i//g);
$nomatch = ($opt =~ s/v//g);
die "Unknown option `$opt'\n" if $opt ne "";
@ARGV = ("-") if $#ARGV < 0;
for $fn1 (@ARGV) {
 for $fn (glob $fn1) {
  if (open FH, "<$fn") {
    $pref = $fn eq "-" ? "" : "$fn:";
    if ($igncase) {
      while (<FH>) {
        print  "$pref$.:$_" if (/$re/i) xor $nomatch;
      }
    } else {
      while (<FH>) {
        print  "$pref$.:$_" if (/$re/) xor $nomatch;
      }
    }
    close FH;
  }
 }
}

SUBTITLE CONVERTER

These days DVD rips are very popular ways to store and watch movies on PCs. High quality video and sound can be stored on one or two conventional data CDs and you have similar playback options as in standard DVDs. One of these options is to display subtitles on the screen. There are different subtitle formats. Most subtitle files are normal text files. However, sometimes the subtitle's timing does match exactly to the sound of your movie at hand. There are several tools on Internet which can be used to fix such problems.

If you do not want to use these rather complex tools, you can use the following "simple" Perl script:

#!/usr/bin/perl
# st_conv.pl - Subtitle conversion tool.
#	See usage below.
# Fedon Kadifeli, November 2002 - February 2005.

use strict;
use warnings;

MAIN:
{
my $shift = 0;
my $shift_time_mode = 0;
my $mult = 1.0;
my $framerate = 1000;
my $fromsub;
my $tosub;
my $total = 0;
my $conv = 0;
my $wconv = 0;
my $o1;
my $o2;
my $subtitle;

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

sub CheckLines {
  my @lines = split /\|/, shift;
  my $nl = 0;
  my $ret = "";
  for (@lines) {
    my $ll = length;
    if ($ll > 50) {
      my $hl = int ($ll / 2);
      s/^(.{$hl,}?.*?) (.*)$/$1|$2/;
      warn "*** At $total. Too long ($ll char) subtitle split!\n";
      $nl++;
    }
    $ret .= "|$_";
    $nl++;
  }
  warn "*** At $total. $nl-line subtitle!\n" if ($nl > 3);
  return substr($ret,1);
} # CheckLines

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

sub TimetoString {
  my $t = shift;
  my $dp = shift;
  my $hh = int ($t / 3600);
  my $mm = int (($t - $hh * 3600) / 60);
  my $ss = int ($t - $hh * 3600 - $mm * 60);
  my $ttt = int (($t - int ($t)) * 1000);
  my $tstr = sprintf ("%02d:%02d:%02d%s%03d", $hh, $mm, $ss, $dp, $ttt);
  return $tstr;
} # TimetoString

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

sub ReadSubtitle {
  return 0 if (eof FH);
  my $ret = 1;
  if ($fromsub) {
    $total++;
    $_ = <FH>;
    if (/^\{(\d*)}{(\d*)}(.*?)\r?\n?$/) {
      $o1 = $1;
      $o2 = $2;
      $subtitle = $3;
      $conv++;
    } else {
      warn "*** At $total. Incorrect .sub format!\n";
      $ret++;
    }
  } else {
    $total++;
    $_ = <FH>;
    unless (/^ *\d+ *\s*$/) {
      warn "*** At $total. Number expected. $_ found!\n";
      $ret++;
    }
    return 0 if (eof FH);
    $_ = <FH>;
    if (/^(\d\d):(\d\d):(\d\d)[\.,](\d\d\d) --> (\d\d):(\d\d):(\d\d)[\.,](\d\d\d).*$/) {
      $o1 = $1*3600 + $2*60 + $3 + $4 / 1000.0;
      $o2 = $5*3600 + $6*60 + $7 + $8 / 1000.0;
      $subtitle = "";
      while (<FH>) {
        last if (/^\s*$/);
        $_ =~ s/\r?\n?$//;
        $subtitle .= "|" . $_;
      }
      $subtitle =~ s#^\|##;
      $conv++;
    } else {
      warn "*** At $total. .srt info expected. $_ found!\n";
      $ret++;
    }
  } 
  return $ret;  # ==1 if OK; >1 if warning(s)
} # ReadSubtitle

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

sub WriteSubtitle {
  $o1 *= $mult;
  $o2 *= $mult;
  $subtitle = "." if $subtitle eq "";
  $subtitle = CheckLines($subtitle);
  if ($tosub) {
    if (!$fromsub) { # .srt -> .sub
      $o1 *= $framerate;
      $o2 *= $framerate;
    }   
    if ($shift) {
      my $shift_frames = $shift;
      $shift_frames *= $framerate if $shift_time_mode;
      $o1 += $shift_frames;
      $o2 += $shift_frames;
    }
    if ($o1 > 0 && $o2 > 0) {
      $o1 = int ($o1 + 0.5);
      $o2 = int ($o2 + 0.5);
      $wconv++;
      print OFH "{$o1}{$o2}$subtitle\r\n";
    }
  } else {
    if ($fromsub) { # .sub -> .srt
      $o1 /= $framerate;
      $o2 /= $framerate;
    }   
    if ($shift) {
      my $shift_time = $shift;
      $shift_time /= $framerate if ! $shift_time_mode;
      $o1 += $shift_time;
      $o2 += $shift_time;
    }
    if ($o1 > 0 && $o2 > 0) {
      $o1 = TimetoString ($o1, ',');
      $o2 = TimetoString ($o2, ',');
      $subtitle =~ s#\|#\r\n#g;
      $wconv++;
      print OFH "$wconv\r\n$o1 --> $o2\r\n$subtitle\r\n\r\n";
    }
  }
} # WriteSubtitle

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

my $usage='
Usage:	st_conv.pl infile outfile [action(s)]

action:	(+|-)(frames|hh:mm:ss.ttt)
	*ddd.ddd
	@framerate [eg. 23.976, 25, 29.97]
';

die "$usage" if (($#ARGV < 1) || ($#ARGV > 4));

my $inf = shift;
my $outf = shift;

for my $action (@ARGV) {
  if ($action =~ /^([-+])(\d\d):(\d\d):(\d\d)[\.,](\d\d\d)$/) {
    $shift = $2*3600 + $3*60 + $4 + $5 / 1000.0;
    $shift = - $shift if ($1 eq "-");
    $shift_time_mode = 1;
  } elsif ($action =~ /^([-+])(\d*)$/) {
    $shift = $action * 1.0;
    $shift_time_mode = 0;
  } elsif ($action =~ /^\*(\d*\.\d*)$/) {
    $mult = $1 * 1.0;
  } elsif ($action =~ /^\@(\d+.?\d*)$/) {
    $framerate = $1 * 1.0;
  } else {
    die "Format of action ($action) is incorrect!\n$usage";
  }
} # for

if ($inf =~ /\.sub$/i) {
  $fromsub = 1;
} elsif ($inf =~ /\.srt$/i) {
  $fromsub = 0;
} else {
  die "File extension of first file must be .sub or .srt!\n$usage";
}
if ($outf =~ /\.sub$/i) {
  $tosub = 1;
} elsif ($outf =~ /\.srt$/i) {
  $tosub = 0;
} else {
  die "File extension of second file must be .sub or .srt!\n$usage";
}
my $frdisp = "";
if ( ($fromsub != $tosub) ||
     ($shift && $fromsub && $tosub && $shift_time_mode) ||
     ($shift && !$fromsub && !$tosub && !$shift_time_mode) ) {
  die "Framerate is not between 10 and 50!\n$usage" if ($framerate < 10) || ($framerate > 50);
  $frdisp = " - At $framerate frames/sec";
}

die "Cannot open input file!\n" unless (open(FH, "<$inf"));
die "Output file $outf exists!\n" if (open(OFH, "<$outf"));
close OFH;
die "Cannot open output file!\n" unless (open(OFH, ">$outf"));

warn "$inf  ==>  $outf\n\n";
warn "Action:\t" .
  "Shift by $shift " . ($shift_time_mode?"seconds":"frames") .
  " - Multiply by $mult" .
  $frdisp . "\n\n";

while (my $ret = ReadSubtitle) {
  WriteSubtitle if $ret == 1;
}

close FH;
close OFH;

warn "*** Conversion error! Input file probably in wrong format!\n" if ($conv != $total);
warn "$wconv out of $total lines converted.\n";
} # MAIN:

This script recognizes two different formats in input files:

  1. The frame format consists of subtitles specified in a single line. This type of files must have the extension .SUB. For example:
    {33642}{33686}- I have to talk to you.|- Talk later?
    Here, the first two numbers represent the starting and ending frame numbers in the movie when the correspong text (the rest of the line) will be displayed.
  2. The time format consists of paragraphs each separated by a blank line. This type of files must have the extension .SRT. For example:
    172
    00:16:21,170 --> 00:16:24,129
    - Can't we go somewhere else?
    - Where?
    Here the first line is the subtitle sequence number, the second line specifies the starting and ending time in the movie when the corresponding text (the remaining lines up to the first empty line) will be displayed.

The script takes at least two parameters: The first one specifies the name of the input file (the file that will be read), the second one specifies the name of the output file (the file that will be created). The file extensions should be either .SUB or .SRT as described above. If they are different, then the necessary file format conversion will be done.

If you specify more that two parameters, these will indicate the actions to be done on subtitles. You can shift forward or backward or multiply the subtitle time information. Allowable formats for actions are:
+frame
-frame
+hh:mm:ss.ttt
-hh:mm:ss.ttt
*ddd.ddd
@framerate (eg. 23.976, 25, 29.97)

The framerate is necessary if you convert a file from .SUB to .SRT or vice versa or if the shift amount is given in a form that is not compatible with the format of the files.

Frame (which must be an integer number) will be added to or subtacted from both frame numbers of each line in the file. Similarly, hh:mm:ss.ttt (which must consist of the four numbers: hours, minutes, seconds, and milliseconds) will be added to or subtacted from both times in the file. The multiplier ddd.ddd (which must be a decimal number like 1.00125) will be multiplied with the subtitle time information in the file.


WEB "BROWSER"

If you want to "browse" some page from an http server on the Internet from command line, this very simple script may help you. This Perl script will connect to the server you specified using the port you give and will request and display a page.

#!/usr/bin/perl
# wb.pl - Simple web "browser".
# Fedon Kadifeli, 1997 - April 2003.

$usage='wb.pl [server [port [URL]]]';
$date='08/04/2003 15:50';
$version='0.03';

die "Usage: $usage\n" if $#ARGV>2;

( $server, $port, $url ) = @ARGV;

$port = 80 unless $port;
$server = 'localhost' unless $server;
$url = '/' unless $url;

$AF_INET = 2;
$SOCK_STREAM = 1;

$SIG{'INT'} = 'dokill';

sub dokill {
  kill 9,$child if $child;
}

$sockaddr = 'S n a4 x8';

($name,$aliases,$proto) = getprotobyname('tcp');
($name,$aliases,$port) = getservbyname($port,'tcp')
    unless $port =~ /^\d+$/;

($name,$aliases,undef,undef,$thataddr) = gethostbyname($server);
die "$server: $!\n" unless defined $thataddr;

$this = pack($sockaddr, $AF_INET, 0, "");
$that = pack($sockaddr, $AF_INET, $port, $thataddr);

@ip = unpack("C4", $thataddr);
print STDERR "Server: @ip - Port : $port - URL : $url\n";

socket(S, $AF_INET, $SOCK_STREAM, $proto) or die "socket: $!\n";
bind(S, $this)   or die "bind: $!\n";
connect(S,$that) or die "connect: $!\n";

select(S); $| = 1; select(STDOUT); 

print S "GET $url HTTP/1.0\n\n";
while( <S> ) {
  print;
}
close (S);

The script takes three parameters. You can use it like this:

perl wb.pl www.kadifeli.com 80 http://www.kadifeli.com/fedon/
perl wb.pl www.hp.com

In the first example we had to use the full URL in the third parameter since www.kadifeli.com is a "virtual host." In the second example, the implied third parameter / was enough.


© April 2003 - February 2015, Fedon Kadifeli.