Perl variable to shell command...?

R

Rohit

Hi, I am trying to use perl local variable with shell command call.

Example:

$filename=myFile.txt

@fileRec=`cat $filename`;

Here shell is not able to identify $filename variable. Any idea or
suggestions?
I am using array of filename so it is necessary for me to use cat with
variable.

Thanks in advance.

~Rohit
 
U

usenet

Hi, I am trying to use perl local variable with shell command call.
Example:
$filename=myFile.txt

You should quote your string literals. And scope your variable (and
'use strict;' at the top of your program). And to make it really
bullet-proof, fully qualify the filename:

my $filename = '/path/to/my/file.txt';
@fileRec=`cat $filename`;
Here shell is not able to identify $filename variable. Any idea or
suggestions?

Your program is started from a directory other than the one your file
resides in. You can do one of the following:
- fully qualify the filenames
- cd to the appropriate directory before running your program
- chdir() to the appropriate directory within your program

FWIW, @fileRec=`cat $filename`; is of dubious quality. If your file
is large your program will crash. It would be safer to open the file
(in Perl) and process it one line at a time in a while{} loop. And
you have better control over your exception handling for error
conditions.

At the very least you should fully qualify your cat command (ie, '/usr/
bin/cat' or whatever). It is a potential security risk to call
unqualified system commands.
 
R

Rohit

You should quote your string literals. And scope your variable (and
'use strict;' at the top of your program). And to make it really
bullet-proof, fully qualify the filename:

my $filename = '/path/to/my/file.txt';


Your program is started from a directory other than the one your file
resides in. You can do one of the following:
- fully qualify the filenames
- cd to the appropriate directory before running your program
- chdir() to the appropriate directory within your program

FWIW, @fileRec=`cat $filename`; is of dubious quality. If your file
is large your program will crash. It would be safer to open the file
(in Perl) and process it one line at a time in a while{} loop. And
you have better control over your exception handling for error
conditions.
Yupe, you are right. My file size is 210KB, and it is failing while I
am piping its output for further processing.

$symbolFile = "$symbolFile[$fileCount]";
....
....
$var123="$symbolFile";
@dataVar = `/bin/cat $var123 | grep -i ^func`

If I remove piping here, it works great. Let me see now perl parsing.
At the very least you should fully qualify your cat command (ie, '/usr/
bin/cat' or whatever). It is a potential security risk to call
unqualified system commands.

Thanks for your comments.

~Rohit
 
T

Tad McClellan

You should quote your string literals. And scope your variable (and
'use strict;' at the top of your program).


And use semicolons between statements.
 
J

J. Gleixner

Rohit said:
On Sep 4, 2:55 pm, Rohit <[email protected]> wrote:
[...]
FWIW, @fileRec=`cat $filename`; is of dubious quality. If your file
is large your program will crash. It would be safer to open the file
(in Perl) and process it one line at a time in a while{} loop. And
you have better control over your exception handling for error
conditions.
Yupe, you are right. My file size is 210KB, and it is failing while I
am piping its output for further processing.

$symbolFile = "$symbolFile[$fileCount]";
...
...
$var123="$symbolFile";
@dataVar = `/bin/cat $var123 | grep -i ^func`

If I remove piping here, it works great. Let me see now perl parsing.

If you remove the pipe, it doesn't "work" at all.

Why are you using cat at all? The grep command takes filenames
as arguments.

man grep

If you want to use perl to read through the file:

perldoc perlintro

Look for "Files and I/O"
 
B

Benoit Lefebvre

Hi, I am trying to use perl local variable with shell command call.

Example:

$filename=myFile.txt

@fileRec=`cat $filename`;

Here shell is not able to identify $filename variable. Any idea or
suggestions?
I am using array of filename so it is necessary for me to use cat with
variable.

Thanks in advance.

~Rohit

I like to do it that way

$filename = "myfile.txt";

$cmd = "cat ". $filename;

@fileRec = `$cmd`;
 
J

Josef Moellers

Benoit said:
I like to do it that way

$filename = "myfile.txt";

$cmd = "cat ". $filename;

@fileRec = `$cmd`;

While this is how I'd do it, too (I can then show the entire command for
debugging purposes), it won't help the OP as the net result won't be any
different.
Most likeley, the file isn't accessable, e.g. because it's in a
different path or it is read-protected, or the OP isn't telling us
everything, as his code is not valid Perl anyway.
 
K

Klaus

[ ...snip... ]

You have replaced your string literal myFile.txt
by a single variable $symbolFile[$fileCount]:
$symbolFile = "$symbolFile[$fileCount]";

While you should quote string literals, you should *not* quote a
single variable.

See perlfaq 4: What's wrong with always quoting ``$vars''?
 
B

Ben Morrow

Quoth Josef Moellers said:
While this is how I'd do it, too (I can then show the entire command for
debugging purposes),

For cases when you need an external command, I'd agree. This is not one
of them: perl is perfectly capable of reading a file on its own:

my @fileRec = do {
open my $FH, '<', 'myFile.txt'
or die "can't read 'myFile.txt': $!";
<$FH>;
};

or indeed

use File::Slurp qw/read_file/;

my @fileRec = read_file 'myFile.txt';
Most likeley, the file isn't accessable, e.g. because it's in a
different path or it is read-protected, or the OP isn't telling us
everything, as his code is not valid Perl anyway.

....except it is, it just doesn't mean what he thinks it does:

~% perl -le'print myFile.txt'
myFiletxt
~%

'myFile' and 'txt' are autoquoted, and the . concatenates them. Yet
another reason why you should always use strictures: in this case, the
rather perversely-named strict 'subs' (it should clearly be strict
'strings') rather than the usual strict 'vars'.

Ben
 
R

Rohit

Quoth Josef Moellers <[email protected]>:





For cases when you need an external command, I'd agree. This is not one
of them: perl is perfectly capable of reading a file on its own:

my @fileRec = do {
open my $FH, '<', 'myFile.txt'
or die "can't read 'myFile.txt': $!";
<$FH>;
};

or indeed

use File::Slurp qw/read_file/;

my @fileRec = read_file 'myFile.txt';


...except it is, it just doesn't mean what he thinks it does:

~% perl -le'print myFile.txt'
myFiletxt
~%

'myFile' and 'txt' are autoquoted, and the . concatenates them. Yet
another reason why you should always use strictures: in this case, the
rather perversely-named strict 'subs' (it should clearly be strict
'strings') rather than the usual strict 'vars'.

Ben

Yupe, thanks everyone. I have replace entirely replaced my code..

for ($fileCount = 0; $fileCount < 3; $fileCount++) {
$symbolFile = $symbolBreakpadFile[$fileCount];
open SYMBFILEHANDLE, "< $symbolFile" or die $!;
@funcRec= <SYMBFILEHANDLE>;
open FHANDLE, "> $SymbolPlistFile[$fileCount]" or die $!;
myMain();
close(SYMBFILEHANDLE);
}

Thanks again for your time and pointing out my mistakes, which I could
have never identified.

Thanks, Rohit

It's a journey from Learning to Learning....which never ends...!
 
B

Ben Morrow

Quoth Rohit said:
Yupe, thanks everyone. I have replace entirely replaced my code..

OK, 'round we go again... :) (please don't be offended by this: the aim
is solely to help you learn better Perl practices).
for ($fileCount = 0; $fileCount < 3; $fileCount++) {

Do you have

use strict;
use warnings;

at the top of your script? If not, you should have, and you should fix
all the error messages you get.

Using a C-style for loop is nearly always a bad idea: Perl has better
ways of iterating over things. In this case, over a list of numbers:

for my $fileCount (0..2) {

The 'my' means the variable doesn't exist outside the for loop, and also
keeps strict happy.

The only reason you need the index at all is because you have two
parallel arrays. This is usually a sign you should have a data
structure, something like

my @symbolFile = (
{
Breakpad => "breakpad #1",
Plist => "plist #1",
},
{
Breakpad => "breakpad #2",
Plist => "plist #2",
},
);

and then you could simply iterate over the array

for my $symbolFile (@symbolFile) {
# use $symbolFile->{Breakpad} and $symbolFile->{Plist}
}

but changing that will require changing the rest of your program, so you
may want to leave it for now.
$symbolFile = $symbolBreakpadFile[$fileCount];

This needs a 'my'.
open SYMBFILEHANDLE, "< $symbolFile" or die $!;

You should use three-arg open, nowadays. You should also keep your
filehandles in variables, and give sensible error messages.

open my $SYMBFILEHANDLE, '<', $symbolFile
or die "can't read '$symbolFile': $!";
@funcRec= <SYMBFILEHANDLE>;
open FHANDLE, "> $SymbolPlistFile[$fileCount]" or die $!;
myMain();

Oh dear, you are passing data to a function by modifying a global value
(in this case, a filehandle). This is a very bad idea: it makes it very
hard to see where values come from when something goes wrong. If you
switch to keeping filehandles in variables you can pass it into the
function as a parameter:

open my $PLIST, '>', $SymbolPlistFile[$fileCount]
or die "can't write '$SymbolPlistFile[$fileCount]': $!";
myMain($PLIST);

and then in myMain:

sub myMain {
my ($PLIST) = @_;

# write to $PLIST instead of FHANDLE
}

Also note that one of the advantages of scoping your variables with my
is you no longer need such long names: you should be able to easily see
the piece of code a variable name is valid over, and see that it is
unique.
close(SYMBFILEHANDLE);

If you use lexical filehandles (filehandles in variables) they close
automatically when the variable goes out of scope. This is a saving if
you're not going to check the return value of close anyway (not
generally necessary on files you are reading, but worth doing on files
you are writing, as an error can be delayed until then).
Thanks again for your time and pointing out my mistakes, which I could
have never identified.

That's quite alright :).

Ben
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,013
Latest member
KatriceSwa

Latest Threads

Top