Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Push value of $_ onto an array for later use without concatenating

Status
Not open for further replies.

tmf33uk

Technical User
Aug 23, 2007
21
GB
Hi,
I´m preparing a perl script that reads a file and then treats it line by line.

The line
print "$_\n";
prints correctly the 4 lines the file it is reading has.

However, the line
print "@lines\n";
prints an output of:
Line1
Line1Line2
Line1Line2Line3
Line1Line2Line3Line4
(a section of the script is included below)

So this shows that "pushing" $_ onto the array @lines as long as there is a new line to read in the file (4 lines in my example) is concatenating the new value to the previous one. How can I do the same thing without concatenating it? I just want the array to contain what is in the file so i can treat the contents line by line.

Thanks in advance,
T.

=====================================================

open (FILE, "< $filename") or die "Cant open $filename: $!";
while (<FILE>)
{
s/"*"//; #ignore comments and ORA_HOME with no db defined
next if /^(\s)*$/; #skip blank lines
chomp; #remove trailing newline
print "$_\n";
push (@lines, $_); #push the data line onto the array
print "@lines\n";
}
close FILE;

 
Ok, I´ve got an answer to my earlier question. My script now looks like this:

open (FILE, "< $filename\n") or die "Cant open $filename: $!\n";
while (<FILE>)
{
s/"*"//; #ignore comments and ORA_HOME with no db defined
next if /^(\s)*$/; #skip blank lines
chomp; #remove trailing newline
@lines= <FILE>;
print "@lines\n";
}
close FILE;

However, the line

print "@lines\n";

is missing out the first line in the file, and the lines after the second one have a small indentation from the left side. Any ideas of why the first line is not included in the array and why the lines are formatted differently after the 2nd line?

Thanks in advance!

T.
 
1. You're reading the file in two different places. See commented code:
Code:
# open the file. so far so good
open (FILE, "< $filename\n") or die "Cant open $filename: $!\n";

# reads the next line of the file into $_
# this will only happen once . . . see below
 while (<FILE>)
 {
 # replace 2 or more consecutive double quotes with nothing
 s/"*"//;                

 # skip blank lines (though the parentheses are unnecessary
 next if /^(\s)*$/;

 # remove trailing newline
 chomp;

 # read the rest of the file into @lines
 # this means that the "while" loop doesn't iterate again
 # as you've now read the whole file
 @lines= <FILE>;

 # print line 2 to the end
 print "@lines\n";
 }
# close the file
close FILE;

2. Printing an array between double quotes results in the elements of the array being printed with the list separator (special variable $" - see perlvar) between them. The default value of $" is a space, so that's why the indentation is occurring. If you don't want that there, try this:
Code:
print @lines, "\n";

To solve you problem, go back to the version of your code in your first post, but move the printing of @lines outside the while loop.
 
Hi Ishnid,

thanks for your help (and the explanations)! I hope you could help me with a loop in the same script that is not doing what I want it to do. I include the whole script at the bottom of this message. The intention is that (1) it reads a file /var/opt/oratab into an array (this I´ve managed to do with your help already), (2) It should go line by line, separating the fields by : so that the 2nd one can be assigned to a variable with which I can run an OS command to check the permissions of bin files within each of these directories.

As it is now, the script prints the @lines array and then it is checking the permissions of the binary files ending in zero in $ORACLE_HOME/bin of the first oratab line, /opt/oracle/product/db10g/bin/*0.

I am not clear as to whether the array has stored the lines from oratab into one line, or it is just the way it lists them. If it lists them all into one line consecutively, then I can see why

my $ORACLE_HOME=$line[1];

only reads the first directory and not one for each line in the oratab. How can I get it to work through the array, line by line? :eek:(

Thanks again!

Teresa.

#################################################
/var/opt/oratab contains:
repo:/opt/oracle/product/db10g:Y
agent:/opt/oracle/product/agent10g:Y
oms:/opt/oracle/product/oms10g:Y
emdiag:/opt/oracle/product/emdiag:Y
##################################################
prueba.pl:

#!/usr/bin/perl

use strict;

my @lines=();
my $line;
my @line=();
my $filename = "/var/opt/oratab";
my $bincero;
my @bincero=();
my $perms;
my $dev;
my $pattern;
my @bin;
my @fields=();

# print "Oratab: $filename\n";
#========================================================
#Read from oratab file
#========================================================
open (FILE, "< $filename\n") or die "Cant open $filename: $!\n";
while (<FILE>)
{
s/"*"//; #ignore comments and ORA_HOME with no db defined
next if /^(\s)*$/; #skip blank lines
chomp;
push (@lines, $_);
}
print @lines, "\n";
close FILE;
foreach $line (@lines)
{
@line= split (/:/, $line);
my $instance=$line[0];
my $ORACLE_HOME=$line[1];
my $linea;
my @bincero = `ls -la $ORACLE_HOME/bin/*0`;
my @binO = `ls -la $ORACLE_HOME/bin/*O`;
# my @allredunbins = (@bincero, @binO); #merges both arrays into one.
#print "Redundant binaries ending in O in $ORACLE_HOME, regardless of perms are as follows:\n @allredunbins\n";
foreach $linea(@bincero)
{
@fields = split(m/[\n\t\s]+/, $linea);
$perms = $fields[0];
$dev = $fields[8];
$pattern = "----------";
# {
if ($perms !~ $pattern) #Check for permissions above 000 in each binary.
{print "em_result: Binary $dev has excessive perms: $perms\n"; }
# }
}
exit 0;
}
##########################################################
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top