How to get all monday (date) for the particular year input - linux

with linux command or perl ,
How to get all monday date for 2010
For example:
20100104 -------- this is jan monday 2010
20100111
20100118
20100125
----
---
---
20101206
20101213
20101220
20101227 -------- this is dec monday 2010

You could use DateTime:
#!/usr/bin/env perl
use strict;
use warnings;
use DateTime;
my $year = 2010;
my $dt = DateTime->new(
'year' => $year,
'month' => 1,
'day' => 1,
);
# find first Monday
while ( $dt->day_name() ne 'Monday' ) {
$dt->add( 'days' => 1 );
}
while ( $dt->year() == $year ) {
print $dt->strftime("%Y%m%d\n");
$dt->add( 'weeks' => 1 );
}

I'd probably do this with DateTime in a very similar manner to Alan's solution. But it's interesting to see how you could also do it using Perl's built-in date-handling facilities.
#!/usr/bin/perl
use strict;
use warnings;
use POSIX 'strftime';
use Time::Local;
my $ONE_DAY = 24 * 60 * 60;
my $ONE_WEEK = 7 * $ONE_DAY;
my $year = shift || 2010;
# Get Jan 1st
my $date = timelocal 0, 0, 0, 1, 0, $year - 1900;
# Get first monday
until (strftime('%a', localtime $date) eq 'Mon') {
$date += $ONE_DAY;
}
while (strftime('%Y', localtime $date) == $year) {
print strftime('%Y%m%d', localtime $date), "\n";
$date += $ONE_WEEK;
}

If you're doing this in Perl, then give Date::Calc a look. I'm a huge fan of Date::Calc, as its large library of functions make these kinds of calculations relatively trivial. For the problem in this question, you could do it with:
use Date::Calc qw(Weeks_in_Year Monday_of_Week);
$wks_in_2010 = Weeks_in_Year(2010);
for ($i = 1; $i <= $wks_in_2010; $i++) {
($mon_year, $mon_month, $mon_day) = Monday_of_Week($i, 2010);
print "$mon_month/$mon_day/$mon_year\n";
}
Remember, Tim Toady.

Related

Active Directory get all user's logon hours(when they're allowed to log in) using powershell

Is it possible to get all the AD user's logon hours and output it into an excel spreadsheet. So something like:
Name
Logon Hours
Bob
9am-6pm
Jane
8am-5pm
Chris
9am-6pm
So far I have Get-AdUser -Filter * -Properties LogonHours | ft Name, LogonHours. However the output is all in binary.
However the output is all in binary.
That happens to be the way AD stores it. The logonHours attribute value consists of 21 bytes, each byte covering an 8-hour window, starting from midnight on Sunday.
As TheMadTechnician notes, converting the byte values to binary/base-2 strings might be the simplest way of accessing each "hour".
With this in mind, we could make a nifty little helper class that can translate the byte array into meaningful logon hour information:
class LogonHourAdapter
{
hidden
[string[]]$_days
LogonHourAdapter([byte[]]$logonHours)
{
if($logonHours.Count -ne 21){
throw [System.ArgumentException]::new('logonHours', "Expected byte array of length 21.")
}
$this._days = [string[]]::new(7)
for($i = 0; $i -lt 7; $i++){
$offset = $i * 3
$this._days[$i] = ($logonHours[$offset..($offset+2)]|ForEach-Object{[convert]::ToString($_,2).PadLeft(8, '0')})-join''
}
}
[bool]
IsAllowedToLogonDuring([DayOfWeek]$day, [int]$hour)
{
if($hour -ge 24){
throw [System.ArgumentOutOfRangeException]::new('hour')
}
return $this._days[$day][$hour] -eq '1'
}
[int[]]
GetLogonHoursOn([DayOfWeek]$day){
$hours = 0..23 |? {$this._days[$day][$_] -eq '1'}
return $hours -as [int[]]
}
}
Now we don't need to worry about parsing the binary data, we just pass the attribute value to an instance of the class:
PS ~> $bob = Get-ADUser Bob -Properties logonHours
PS ~> $bobHours = [LogonHourAdapter]::new($bob.logonHours)
PS ~> $bobHours.IsAllowedToLogonDuring('Monday', 9) # Bob is allowed to logon after 9am
True
PS ~> $bobHours.IsAllowedToLogonDuring('Monday', 6) # But not earlier!
False
Next, we'll want to track "ranges" - contiguous periods throughout each day where the user is allowed to logon.
For each day, simply "walk" through each hour from 0 through 23 and start tracking a new range everytime there's a break:
# Prepare our logon hour adapter
$lha = [LogonHourAdapter]::new($bob.logonHours)
# Extract ranges for each day of the week
$ranges = foreach($day in -split 'Sunday Monday Tuesday Wednesday Thursday Friday Saturday'){
$currRange = $null
0..23|%{
if($lha.IsAllowedToLogonDuring($day, $_)){
if(-not $currRange){
$currRange = [pscustomobject]#{ Day = [DayOfWeek]$day; From = $_; To = $null}
}
$currRange.To = $_ + 1
}else{
if($currRange){
$currRange
$currRange = $null
}
}
}
if($currRange){
$currRange
}
}
Now we just need to group them together so we can express "8-16 (Monday, Tuesday, Friday)" instead of "8-16 (Monday), 8-16 (Tuesday), 8-16 (Wednesday) ... etc.":
$label = $ranges |Group-Object From,To |Sort Count -Descending |ForEach-Object {
'{0:00}-{1:00} ({2})' -f $_.Group[0].From,$_.Group[0].To,(($_.Group.Day |Sort) -join', ')
}
And $label now contains a more human readable version of Bob's logonHours:
PS ~> $label
08-16 (Monday, Tuesday, Wednesday, Thursday, Friday, Saturday)

How to move the decimal point N places to the left efficiently?

I have a bunch of decimal numbers (as strings) which I receive from an API. I need to 'unscale' them, i.e. divide them by some power of 10. This seems a simple task for integers, but I have decimals with no guaranteed range. So, basically I need a function that works like this:
move_point "12.34" 1; # "1.234"
move_point "12.34" 5; # "0.0001234"
I'd rather not use floats to avoid any rounding errors.
This is a bit verbose, but should do the trick:
sub move_point {
my ($n, $places) = #_;
die 'negative number of places' if $places < 0;
return $n if $places == 0;
my ($i, $f) = split /\./, $n; # split to integer/fractional parts
$places += length($f);
$n = sprintf "%0*s", $places+1, $i.$f; # left pad with enough zeroes
substr($n, -$places, 0, '.'); # insert the decimal point
return $n;
}
Demo:
my $n = "12.34";
for my $p (0..5) {
printf "%d %s\n", $p, move_point($n, $p);
}
0 12.34
1 1.234
2 0.1234
3 0.01234
4 0.001234
5 0.0001234
Unless your data has contains values with significantly more digits than you have shown then a floating-point value has more than enough accuracy for your purpose. Perl can reliably reproduce up to 16-digit values
use strict;
use warnings 'all';
use feature 'say';
say move_point("12.34", 1); # "1.234"
say move_point("12.34", 5); # "0.0001234"
say move_point("1234", 12);
say move_point("123400", -9);
sub move_point {
my ($v, $n) = #_;
my $dp = $v =~ /\.([^.]*)\z/ ? length $1 : 0;
$dp += $n;
$v /= 10**$n;
sprintf '%.*f', $dp < 0 ? 0 : $dp, $v;
}
output
1.234
0.0001234
0.000000001234
123400000000000
Update
If the limits of standard floating-point numbers are actually insuffcient for you then the core Math::BigFloat will do what you need
This program shows a number with sixteen digits of accuracy, multiplied by everything from 10E-20 to 10E20
use strict;
use warnings 'all';
use feature 'say';
use Math::BigFloat;
for ( -20 .. 20 ) {
say move_point('1234567890.1234567890', $_);
}
sub move_point {
my ($v, $n) = #_;
$v = Math::BigFloat->new($v);
# Build 10**$n
my $mul = Math::BigFloat->new(10)->bpow($n);
# Count new decimal places
my $dp = $v =~ /\.([^.]*)\z/ ? length $1 : 0;
$dp += $n;
$v->bdiv($mul);
$v->bfround(-$dp) if $dp >= 0;
$v->bstr;
}
output
123456789012345678900000000000
12345678901234567890000000000
1234567890123456789000000000
123456789012345678900000000
12345678901234567890000000
1234567890123456789000000
123456789012345678900000
12345678901234567890000
1234567890123456789000
123456789012345678900
12345678901234567890
1234567890123456789
123456789012345678.9
12345678901234567.89
1234567890123456.789
123456789012345.6789
12345678901234.56789
1234567890123.456789
123456789012.3456789
12345678901.23456789
1234567890.123456789
123456789.0123456789
12345678.90123456789
1234567.890123456789
123456.7890123456789
12345.67890123456789
1234.567890123456789
123.4567890123456789
12.34567890123456789
1.234567890123456789
0.1234567890123456789
0.01234567890123456789
0.001234567890123456789
0.0001234567890123456789
0.00001234567890123456789
0.000001234567890123456789
0.0000001234567890123456789
0.00000001234567890123456789
0.000000001234567890123456789
0.0000000001234567890123456789
0.00000000001234567890123456789

Perl Conditions

Trying to iterate through two files. Everything works although once I get to the negation of my if statement it messes everything up. The only thing that will print is the else statement
Please disregard any unused variables, when defined. Will clean it up after.
#!/usr/bin/perl
#
# Packages and modules
#
use strict;
use warnings;
use version; our $VERSION = qv('5.16.0'); # This is the version of Perl to be used
use Text::CSV 1.32; # We will be using the CSV module (version 1.32 or higher)
# to parse each line
#
# readFile.pl
# Authors: schow04#mail.uoguelph + anilam#mail.uoguelph.ca
# Project: Lab Assignment 1 Script (Iteration 0)
# Date of Last Update: Monday, November 16, 2015.
#
# Functional Summary
# readFile.pl takes in a CSV (comma separated version) file
# and prints out the fields.
# There are three fields:
# 1. name
# 2. gender (F or M)
# 3. number of people with this name
#
# This code will also count the number of female and male
# names in this file and print this out at the end.
#
# The file represents the names of people in the population
# for a particular year of birth in the United States of America.
# Officially it is the "National Data on the relative frequency
# of given names in the population of U.S. births where the individual
# has a Social Security Number".
#
# Commandline Parameters: 1
# $ARGV[0] = name of the input file containing the names
#
# References
# Name files from http://www.ssa.gov/OACT/babynames/limits.html
#
#
# Variables to be used
#
my $EMPTY = q{};
my $SPACE = q{ };
my $COMMA = q{,};
my $femalecount = 0;
my $malecount = 0;
my $lines = 0;
my $filename = $EMPTY;
my $filename2 = $EMPTY;
my #records;
my #records2;
my $record_count = -1;
my $top_number = 0;
my $male_total = 0;
my $male_count = 0;
my #first_name;
my #gender;
my #first_name2;
my #number;
my $count = 0;
my $count2 = 0;
my $csv = Text::CSV->new({ sep_char => $COMMA });
#
# Check that you have the right number of parameters
#
if ($#ARGV != 1) {
print "Usage: readTopNames.pl <names file> <course names file>\n" or
die "Print failure\n";
exit;
}
$filename = $ARGV[0];
$filename2 = $ARGV[1];
#
# Open the input file and load the contents into records array
#
open my $names_fh, '<', $filename
or die "Unable to open names file: $filename\n";
#records = <$names_fh>;
close $names_fh or
die "Unable to close: $ARGV[0]\n"; # Close the input file
open my $names_fh2, '<', $filename2
or die "Unable to open names file: $filename2\n";
#records2 = <$names_fh2>;
close $names_fh2 or
die "Unable to close: $ARGV[1]\n"; # Close the input file
#
# Parse each line and store the information in arrays
# representing each field
#
# Extract each field from each name record as delimited by a comma
#
foreach my $class_record (#records)
{
chomp $class_record;
$record_count = 0;
$count = 0;
foreach my $name_record ( #records2 )
{
if ($csv->parse($name_record))
{
my #master_fields = $csv->fields();
$record_count++;
$first_name[$record_count] = $master_fields[0];
$gender[$record_count] = $master_fields[1];
$number[$record_count] = $master_fields[2];
if($class_record eq $first_name[$record_count])
{
if($gender[$record_count] eq 'F')
{
print("$first_name[$record_count] ($record_count)\n");
}
if($gender[$record_count] eq 'M')
{
my $offset = $count - 2224;
print("$first_name[$record_count] ($offset)\n");
}
}
} else {
warn "Line/record could not be parsed: $records[$record_count]\n";
}
$count++;
}
}
#
# End of Script
#
Adam (187)
Alan (431)
Alejandro (1166)
Alex (120)
Alicia (887)
Ambrose (305)
Caleb (794)
Sample output from running the following code.
This is correct: Although if a name is not found in the second file it is supposed to say:
Adam (187)
Alan (431)
Name (0)
Alejandro (1166)
Alex (120)
Alicia (887)
Ambrose (305)
Caleb (794)
That is what the else is supposed to find. Whether the if statement returned nothing.
else {
print("$first_name[$record_count] (0)\n");
}
The output that i get when i add that else, to account for the negation is literally:
Elzie (0)
Emer (0)
Enna (0)
Enriqueta (0)
Eola (0)
Eppie (0)
Ercell (0)
Estellar (0)
It's really tough to help you properly without better information, so I've written this, which looks for each name from the names file in the master data file and displays the associated values
There's never a reason to write a long list of declarations like that at the top of a program, and you've written way too much code before you started debugging. You should write no more than three or four lines of code before you test that it works and carry on adding to it. You've ended up with 140 lines — mostly of them comments — that don't do what you want, and you're now lost as to what you should fix first
I haven't been able to fathom what all your different counters are for, or why you're subtracting a magic 2224 for male records, so I've just printed the data directly from the master file
I hope you'll agree that it's far clearer with the variables declared when they're required instead of making a huge list at the top of your program. I've dropped the arrays #first_name, #gender and #number because you were only ever using the latest value so they had no purpose
#!/usr/bin/perl
use strict;
use warnings;
use v5.16.0;
use autodie;
use Text::CSV;
STDOUT->autoflush;
if ( #ARGV != 2 ) {
die "Usage: readTopNames.pl <names file> <master names file>\n";
}
my ( $names_file, $master_file ) = #ARGV;
my #names = do {
open my $fh, '<', $names_file;
<$fh>;
};
chomp #names;
my #master_data = do {
open my $fh, '<', $master_file;
<$fh>;
};
chomp #master_data;
my $csv = Text::CSV->new;
for my $i ( 0 .. $#names ) {
my $target_name = $names[$i];
my $found;
for my $j ( 0 .. $#master_data ) {
my $master_rec = $master_data[$j];
my $status = $csv->parse($master_rec);
unless ( $status ) {
warn qq{Line/record "$master_rec" could not be parsed\n};
next;
}
my ( $name, $gender, $count ) = $csv->fields;
if ( $name eq $target_name ) {
$found = 1;
printf "%s %s (%d)\n", $name, $gender, $count;
}
}
unless ( $found ) {
printf "%s (%d)\n", $target_name, 0;
}
}
output
Adam F (7)
Adam M (5293)
Alan F (9)
Alan M (2490)
Name (0)
Alejandro F (6)
Alejandro M (2593)
Alex F (157)
Alex M (3159)
Alicia F (967)
Ambrose M (87)
Caleb F (14)
Caleb M (9143)
4 changes proposed:
foreach my $class_record (#records)
{
chomp $class_record;
$record_count = 0;
$count = 0;
# add found - modification A
my $found = 0;
foreach my $name_record ( #records2 )
{
# should not be here
#$record_count++;
if ($csv->parse($name_record))
{
my #master_fields = $csv->fields();
$record_count++;
$first_name[$record_count] = $master_fields[0];
$gender[$record_count] = $master_fields[1];
$number[$record_count] = $master_fields[2];
if($class_record eq $first_name[$record_count])
{
if($gender[$record_count] eq 'F')
{
print("$first_name[$record_count] ($record_count)\n");
}
if($gender[$record_count] eq 'M')
{
my $offset = $count - 2224;
print("$first_name[$record_count] ($offset)\n");
}
# modification B - set found =1
$found = 1;
#last; # no need to keep looping
next; # find next one if try to find more than 1
}
} else {
warn "Line/record could not be parsed: $records[$record_count]\n";
}
$count++;
}
# modification C -
if($found){
}else{
print "${class_record}(0)\n";
}
}

Splitting a numerical string in Perl

I have a numerical string:
"13245988"
I want to split before and after consecutive numbers.
Expected output is:
1
32
45
988
Here is what I've tried:
#!/usr/bin/perl
use strict;
use warnings;
my $a="132459";
my #b=split("",$a);
my $k=0;
my #c=();
for(my $i=0; $i<=#b; $i++) {
my $j=$b[$i]+1;
if($b[$i] == $j) {
$c[$k].=$b[$i];
} else {
$k++;
$c[$k]=$b[$i];
$k++;
}
}
foreach my $z (#c) {
print "$z\n";
}
Editing based on clarified question. Something like this should work:
#!/usr/bin/perl
use strict;
use warnings;
my $a = "13245988";
my #b = split("",$a);
my #c = ();
push #c, shift #b; # Put first number into result.
for my $num (#b) { # Loop through remaining numbers.
my $last = $c[$#c] % 10; # Get the last digit of the last entry.
if(( $num <= $last+1) && ($num >= $last-1)) {
# This number is within 1 of the last one
$c[$#c] .= $num; # Append this one to it
} else {
push #c, $num; # Non-consecutive, add a new entry;
}
}
foreach my $z (#c) {
print "$z\n";
}
Output:
1
32
45
988

Perl code using a text file

Why is my perl code not printing out anything? I have been working on this for a while now and i am using a text file which has a ton of different data which each on of my arrays are sepearated by a comma meaning it is a column.
this is my code:
#!/usr/bin/perl
open (FILE, 'census2008.txt');
my #SumLevArray;
my #StNameArray;
my #CtyNameArray;
my #PopEstimateArary;
my #BirthsArray;
my #DeathsArray;
$i = 0;
$temp = 0;
$lowestBirthRates = 100000000;
$highestBirthRates = 0;
$size = 0;
while (<FILE>)
{
chomp;
($sumlev, $stname,$ctyname,$popestimate2008,$births2008,$deaths2008) = split(",");
push (#SumLevArray, $sumlev);
push (#StNameArray, $stname);
push (#CtyNameArray, $ctyname);
push (#PopEstimateArary, $popestimate2008);
push (#BirthsArray, $births2008);
push (#DeathsArray, $deaths2008);
}
$size = #BirthsArray;
while ($i < $size)
{
if($SumLevArray[$i] == " 040"){
$temp = $BirthsArray[$i]/$PopEstimateArary[$i]/541;
if(($lowestBirthRates > $temp) &&($temp > 0)){
$lowestBirthRates = $temp;
}
if($highestBirthRates < $temp){
$highestBirthRates = $temp;
}
}
$i = $i + 1;
}
print "\n";
print "Lowest birth rate in LOW-STATE: ";
print $lowestBirthRates;
print " per 541\n";
print "Highest birth rate in HIGH-STATE: ";
print $highestBirthRates;
print " per 541\n";
print "In Washington:\n";
print " Lowest birth rate in LOW-COUNTY County, WA: x.xxx per 541\n";
print " Highest birth rate in HIGH-COUNTY County, WA: x.xxx per 541\n";
close (FILE);
exit
The best tool to help you out here is use strict; use warnings;. Make it a point to put it at the top of every script you write as it will save you a ton of time debugging trivial issues.
Here, there are a couple of is that are missing their $ sigil.
Also, consider studying the Perl data structure cookbook: perldoc perldsc. An array of hashes (technically hashrefs) would be a more scalable choice of data structure to store your data.
Beyond using Text::CSV as others have suggested, just for fun I have rewritten the code as I might have written it. It includes many of the suggestions made here and a few of my personal style choices. If you have any questions about it please ask. Also if you can post some sample data, I can check to see that it works.
#!/usr/bin/env perl
use strict;
use warnings;
my $lowestBirthRates = 100000000;
my $highestBirthRates = 0;
my $filename = 'census2008.txt';
open (my $fh, '<', $filename) or die "Cannot open $filename: $!";
my %data;
while (<$fh>) {
chomp;
my ($sumlev, $stname,$ctyname,$popestimate2008,$births2008,$deaths2008) = split(",");
push (#{$data{SumLev}}, $sumlev);
push (#{$data{StName}}, $stname);
push (#{$data{CtyName}}, $ctyname);
push (#{$data{PopEstimate}}, $popestimate2008);
push (#{$data{Births}}, $births2008);
push (#{$data{Deaths}}, $deaths2008);
}
my $i = 0;
my $size = #{$data{Births}};
while ($i < $size) {
if ( $data{SumLev}[$i] eq " 040" ){
#if ( $data{SumLev}[$i] == 40 ){
my $temp = $data{Births}[$i] / $data{PopEstimate}[$i] / 541;
if( $lowestBirthRates > $temp && $temp > 0 ){
$lowestBirthRates = $temp;
}
if ( $highestBirthRates < $temp ){
$highestBirthRates = $temp;
}
}
$i++;
}
print <<REPORT;
Lowest birth rate in LOW-STATE: $lowestBirthRates per 541
Highest birth rate in HIGH-STATE: $highestBirthRates per 541
In Washington:
Lowest birth rate in LOW-COUNTY County, WA: x.xxx per 541
Highest birth rate in HIGH-COUNTY County, WA: x.xxx per 541
REPORT
if you have the luxury of having Perl version 5.14 or greater installed, you can use an even clearer syntax, where push can take references directly, and where each can give the index in question as well as the value.
#!/usr/bin/env perl
use strict;
use warnings;
use 5.14.0;
my $lowestBirthRates = 100000000;
my $highestBirthRates = 0;
my $filename = 'census2008.txt';
open (my $fh, '<', $filename) or die "Cannot open $filename: $!";
my %data = (
SumLev => [],
StName => [],
CtyName => [],
PopEstimate => [],
Births => [],
Deaths => [],
);
while (<$fh>) {
chomp;
my ($sumlev, $stname,$ctyname,$popestimate2008,$births2008,$deaths2008) = split(",");
push ($data{SumLev}, $sumlev);
push ($data{StName}, $stname);
push ($data{CtyName}, $ctyname);
push ($data{PopEstimate}, $popestimate2008);
push ($data{Births}, $births2008);
push ($data{Deaths}, $deaths2008);
}
while (my ($i, $births) = each $data{Births}) {
if ( $data{SumLev}[$i] eq " 040" ){
#if ( $data{SumLev}[$i] == 40 ){
my $temp = $births / $data{PopEstimate}[$i] / 541;
if( $lowestBirthRates > $temp && $temp > 0 ){
$lowestBirthRates = $temp;
}
if ( $highestBirthRates < $temp ){
$highestBirthRates = $temp;
}
}
}
print <<REPORT;
Lowest birth rate in LOW-STATE: $lowestBirthRates per 541
Highest birth rate in HIGH-STATE: $highestBirthRates per 541
In Washington:
Lowest birth rate in LOW-COUNTY County, WA: x.xxx per 541
Highest birth rate in HIGH-COUNTY County, WA: x.xxx per 541
REPORT
Finally here is an implementation using Tie::Array::CSV which I wrote to be able to use a CSV file just like a 2D array in Perl (i.e. Array of ArrayRefs). It uses Text::CSV to do the parsing and Tie::File to do line access. This means that you don't need to store all the data in memory like in the previous examples.
#!/usr/bin/env perl
use strict;
use warnings;
use Tie::Array::CSV;
my $lowestBirthRates = 100000000;
my $highestBirthRates = 0;
my $filename = 'census2008.txt';
tie my #data, 'Tie::Array::CSV', $filename
or die "Cannot tie $filename: $!";
foreach my $row (#data) {
my ($sumlev, $stname, $ctyname, $popest, $births, $deaths) = #$row;
if ( $sumlev eq " 040" ){
#if ( $sumlev == 40 ){
my $temp = $births / $popest / 541;
if( $lowestBirthRates > $temp && $temp > 0 ){
$lowestBirthRates = $temp;
}
if ( $highestBirthRates < $temp ){
$highestBirthRates = $temp;
}
}
}
print <<REPORT;
Lowest birth rate in LOW-STATE: $lowestBirthRates per 541
Highest birth rate in HIGH-STATE: $highestBirthRates per 541
In Washington:
Lowest birth rate in LOW-COUNTY County, WA: x.xxx per 541
Highest birth rate in HIGH-COUNTY County, WA: x.xxx per 541
REPORT
Try:
open (FILE, 'census2008.txt') or die $!;
The open may be failing without you knowing it.
When you print something, ending it with a newline will cause it to be printed immediately, otherwise the text goes to the print buffer but the buffer is not flushed.
You should unbuffer stdout.
Add the following after #!/usr/bin/perl
$| = 1;
Having said that, here are a couple other things I would suggest:
1.) At minimum use strict; (use warnings is also advised)
Strict will force you to use "my" to declare your variables where you don't already do so. I can't tell you the number of times I've seen a programmer search and search for a bug that is easily detectable when turning on strict checking. (Typos on var names is a common one)
2.) Use the following for open
open($FILE, "<", 'census2008.txt') || die("Cannot open file!");
This will not only inform you if a file can't be opened for writing (due to the use of die),
but using $FILE instead of a raw file handle will cause the file to be closed automatically when it
goes out of scope.
Try modifying your first lines of code to:
#!/usr/bin/perl
use strict;
use warnings;
$| = 1; #
open (FILE, 'census2008.txt');
After solving the errors/warnings that are appearing, all should be ok.
To access the array you use i instead of $i as index.
Beyond this, I don't understand what you want to do inside the while loop.
There is a problem in the line:
if($SumLevArray[$i] == " 040"){
This line is evaluated to true for many values of $SumLevArray[$i] ie "40", "040", " 00040 "
if $SumLevArray[$i] is an integer, this line should be:
if($SumLevArray[$i] == 40){
if $SumLevArray[$i] is a string, this line should be:
if($SumLevArray[$i] eq " 040"){

Resources