How probably not to hand over a variable from one perl script to another

  • Thread starter Markus Hänchen
  • Start date
M

Markus Hänchen

Hi,

I guess there are better ways to hand over a variable from one perl
script to another. Knowing very little about Perl I came up with this
solution:

$variable = 1;
open TEMP, ">temp.txt";
truncate TEMP, 1;
print TEMP "$variable\n";
close TEMP;
system "runit.pl";
#! /usr/bin/perl
@ARGV = qw# temp.txt #;
while (defined($line = <>)) {
$cta += 1;
@inval{$cta} = $line;
}
chomp($variable = $inval{1});

Cheers,

Markus
 
U

usenet

Markus said:
I guess there are better ways to hand over a variable

You could say that. If that was how Perl passed variables, I'd be using
Python.

Read up on how @ARGV works.
 
M

Markus Hänchen

Now, I don't see a good reason in this case for using temporary files.
Why not pass the argument directly on the command line?

system 'runit.pl', $variable;

Thanks a lot for your detailed advice, I'll try to digest it one by
one. Here is the bit I thought would help me most, unfortunately it
does not work (I guess because there is something I do not understand
here):

$variable = 1;
system 'runit.pl', $variable;
#! /usr/bin/perl
print "$variable \n";
 
M

Markus Hänchen

Oops - meant to give you a reference:

perldoc perlvar

Thanks for your advice, I have read that reference but it is way too
comprehensive. My only knowledge of Perl comes from reading the first
half of the book 'Learning Perl' by Phoenix and Schwartz.
I need simple examples (as I found them in the book), the original Perl
documentation is way too difficult for me in most cases.

I am coming from Matlab, there handing over a variable to another
script or function is done either by using it as an invocation argument
or by making the variable global.
I have the feeling that @ARGV might help me but I need an example of
how this is done, and an example which does not have other code in it
that I do not understand.

I know that what I call 'other code' might only be useful conventions
but in 'Learning Perl' one starts without these conventions, because
you first have to understand the basics before you comprehend why
conventions are useful and how they work.
 
P

Paul Lalli

Markus said:
Thanks a lot for your detailed advice, I'll try to digest it one by
one. Here is the bit I thought would help me most, unfortunately it
does not work (I guess because there is something I do not understand
here):

$variable = 1;
system 'runit.pl', $variable;

#! /usr/bin/perl
print "$variable \n";

First, put the lines:
use strict;
use warnings;

in every script you write. Right below the shebang. They will catch
90% of the errors you make - including this one.

@ARGV is the array that contains the arguments passed to your Perl
program. In this example, you ran the program runit.pl with an
argument of whatever was inside $variable. Therefore, @ARGV in
runit.pl contains exactly one element - whatever was in $variable when
runit.pl was called from the previous script.

Simplify things a little - make this one program, not two. Say you
have your program runit.pl. On the command line, you type:
../runit.pl foo 32 "hello world"

In that case, runit.pl's @ARGV will contain three elements: the string
'foo', the number 32, and the string 'hello world'.

If you were to type on your command line:
../runit.pl
then runit.pl's @ARGV would be empty.

Now, in your situation, you are using a separate program to call
runit.pl, rather than typing it on the command line. That's the only
difference. When you use the system() function, Perl executes the
program that you passed as system()'s first argument, passing that
program the remaining arguments.

Does that help to clarify at all?

Paul Lalli
 
M

Markus Hänchen

$variable = 5;
system 'runit.pl', $variable;

#! /usr/bin/perl
print "$variable \n";

Thought, this might work instead:

#! /usr/bin/perl
$variable = @ARGV;
print "$variable \n";

But, helas, nope.
 
D

David Squire

Markus said:
I have the feeling that @ARGV might help me but I need an example of how
this is done, and an example which does not have other code in it that I
do not understand.


----test.pl----

#!/usr/bin/perl

use strict;
use warnings;

print $ARGV[0];

----

prompt>./test.pl 4.5
4.5

----

Note this is really a question about command line arguments, not passing
perl variables between perl scripts.


DS
 
P

Paul Lalli

Markus said:
Thought, this might work instead:

#! /usr/bin/perl
$variable = @ARGV;
print "$variable \n";

This is known as "throwing it at the wall and seeing what sticks" and
is a very poor method of programming. Please go read a decent tutorial
on Perl. How to get one item out of an array is a very basic concept.
If you are a beginner, that's fine. We all were at one point. But you
must accept that you are a beginner, and *learn* the language, not just
type random lines of code until something works.

There are several good tutorials out there. I suggest you open your
console and type:
perldoc perlintro
followed by
perldoc perlsyn
and
perldoc perldata

Paul Lalli
 
J

Jürgen Exner

Markus said:
Thought, this might work instead:

#! /usr/bin/perl
$variable = @ARGV;

Ok, now $variable contains the number or arguments that were passed to the
script.
Is that what you want?

jue
 
M

Markus Hänchen

Now, in your situation, you are using a separate program to call
runit.pl, rather than typing it on the command line. That's the only
difference. When you use the system() function, Perl executes the
program that you passed as system()'s first argument, passing that
program the remaining arguments.

Does that help to clarify at all?

Paul Lalli

Thanks a lot. I understood $ARGV, I did not know that the equivalent of
typing "./runit.pl 'Hello World'" at the command line would be: "system
'runit8.pl', 'Hello World';". And I still do not understand why a
global variable is global enough to mess up things (i.e. requiring the
use of 'my') but not global enough to be just available.

But more importantly, how does this work for arrays and hashes? (Since
taking the array apart and putting it back together was most of the
work in my previous approach using a temp file.)
 
D

David Squire

Markus said:
Thanks a lot. I understood $ARGV, I did not know that the equivalent of
typing "./runit.pl 'Hello World'" at the command line would be: "system
'runit8.pl', 'Hello World';". And I still do not understand why a global
variable is global enough to mess up things (i.e. requiring the use of
'my') but not global enough to be just available.

Global variables are global to a program, not a computer (and the 'my'
issue here is a red herring. 'use strict;' requires you to declare
variables with 'my' to help save you from typos magically creating new
variables).
But more importantly, how does this work for arrays and hashes? (Since
taking the array apart and putting it back together was most of the work
in my previous approach using a temp file.)

You appear still to be wanting to do something that can't be done[1].
Variables in separate programs cannot be passed to one another as
variables. Stuff on the command line is just text.


DS

[1] Except by using protocols (and modules that understand them) that
handle the serialization and reconstruction of the variables for you,
such as COM, CORBA, SOAP, etc.
 
M

Markus Hänchen

Note this is really a question about command line arguments, not
passing perl variables between perl scripts.

I am realising this. In other words, instead of writing the values of
the variables to a temp file (my original approach), I am writing them
to the command line and reading them back from there, probably a better
approach but stil a pain for arrays and hashes (which I have to take
apart and reassemble for both approaches).
 
P

Paul Lalli

Thanks a lot. I understood $ARGV,

No, you don't. $ARGV is a *completely* separate concept that has
nothing to do with anything else talked about in this thread. The
previous discussion is entirely about @ARGV. They are not the same
variable.
I did not know that the equivalent of
typing "./runit.pl 'Hello World'" at the command line would be: "system
'runit8.pl', 'Hello World';". And I still do not understand why a
global variable is global enough to mess up things (i.e. requiring the
use of 'my') but not global enough to be just available.

I have *no* idea what you mean by this. Can you please explain?

If you're talking about the variable you were trying to "pass" from one
script to another its because of exactly that reason - they are two
completely different scripts. Two completely different *processes*.
They are not at all related. system() is used to run an external
command - the language in which that command is written is wholly
irrelevant.
But more importantly, how does this work for arrays and hashes? (Since
taking the array apart and putting it back together was most of the
work in my previous approach using a temp file.)

It doesn't. That's why people in this thread have been telling you to
do this the *right* way. Don't use two separate and distinct scripts.
Write one script, and write a module that script uses. That module
will contain one or more functions your module can call, and you can
pass arrays and hashes to and from functions arbitrarily.

Paul Lalli
 
J

Jürgen Exner

Markus said:
On 2006-08-03 14:34:48 +0200, "Paul Lalli" <[email protected]> said: [...]
difference. When you use the system() function, Perl executes the
program that you passed as system()'s first argument, passing that
program the remaining arguments.

Thanks a lot. I understood $ARGV,

What does $ARGV have to do with system() and command line arguments?
From perldoc perlvar:
I did not know that the equivalent
of typing "./runit.pl 'Hello World'" at the command line would be:
"system 'runit8.pl', 'Hello World';".

Well, kinda sort of. For once the first argument is more like './runit.pl'
rather than 'runit8.pl'. Yes, those nitpicking details are important.
Computers are notoriuously unforegiving when you make a typo.
And second for this example the command is not passed to the shell but
exec()uted directly. That means any shell meta characters are not evaluated
but passed directly.
But more importantly, how does this work for arrays and hashes?

Command line arguments are nice to pass small sets of information. They are
unsuitable for large sets and most OS even impose a limit to the maximum
lenght of the command line. If you still want to pass the content of a whole
array or hash it's easy enough to do:

In the calling program:
system 'myotherprogram', @myarray;
In the called program:
@mynewarray = @ARGV;

But as mentioned before that can easily exceed the limits of your OS.

A better method is to use one of the standard methods for data passing:
files, pipes, sockets, shared memory, ....
(Since
taking the array apart and putting it back together was most of the
work in my previous approach using a temp file.)

Why would you need to take the array apart and put it back together?

In the program that writes the file:
print @myarray;
In the program that reads the file (after opening file handle FH):
@mynewarray = <FH>;

jue


jue
 
M

Markus Hänchen

This is known as "throwing it at the wall and seeing what sticks" and
is a very poor method of programming. Please go read a decent tutorial
on Perl. How to get one item out of an array is a very basic concept.
If you are a beginner, that's fine. We all were at one point. But you
must accept that you are a beginner, and *learn* the language, not just
type random lines of code until something works.

Thanks for the tutorials. About the 'throwing it at the wall', I did
read the first half of a good book on Perl (and browse and search it as
well as the internet before posting here) but there this saying about
learning by doing and learning by making mistakes.

I know how to get an item out of an array but if the array contains
only one element calling the array without any arguments should give me
that element, Perl should be smart enough to do this (and I guess it
would be, were it not for the fact that @arrayname is reserved to give
me the number of elements of an array, which I did not know since I
always used $#arrayname to get the length of an array).
 
P

Paul Lalli

Markus said:
I know how to get an item out of an array

No, apparently you do not.
but if the array contains
only one element calling the array without any arguments should give me
that element, Perl should be smart enough to do this

Ahhh, so it's the *language*'s fault that your programs aren't working.
Okay.

Because the language does not do what *you* want it to do does not mean
the language is in some way deficient. To be blunt, it means that you
are.

An array evaluated in a scalar context gives the size of that array.
That is a feature, and an often used one.
(and I guess it
would be, were it not for the fact that @arrayname is reserved to give
me the number of elements of an array, which I did not know since I
always used $#arrayname to get the length of an array).

$#arrayname does *not* give you the "length" (I assume you mean "size")
of the array. It gives you the last index of the array.

Here's a quick summary:

my $size_of_array = @array;
my $last_index_of_array = $#array;
my ($first_element_of_array) = @array;
my $first_element_of_array = $array[0];

Paul Lalli
 
D

David Squire

Markus said:
I know how to get an item out of an array but if the array contains only
one element calling the array without any arguments should give me that
element, Perl should be smart enough to do this

It is. You need to read up on list vs scalar context in Perl.

----

#!/usr/bin/perl

use strict;
use warnings;

my @test_array = qw (frog);
my ($element) = @test_array;
print $element;

----

Output:

frog

(and I guess it would
be, were it not for the fact that @arrayname is reserved to give me the
number of elements of an array, which I did not know since I always used
$#arrayname to get the length of an array).

Well, first this is not about @arrayname being reserved, it's about what
happens when you use it in a scalar context. Secondly, they don't return
the same thing. scalar(@arrayname) gives the number of elements in the
array (length), whereas $#arrayname gives in the index of the last
element (which is one less).


DS
 
M

Markus Hänchen

No, you don't. $ARGV is a *completely* separate concept that has
nothing to do with anything else talked about in this thread. The
previous discussion is entirely about @ARGV. They are not the same
variable.

Typing '$ARGV' was a typo, I naturally meant '@ARGV'.
I have *no* idea what you mean by this. Can you please explain?

On the advice of David Squire I used 'strict' which gave me a
warning/error when I tried to use
$variable = $ARGV[0] and no warning/error when I used my($variable) =
$ARGV[0] from which I drew the wrong conclusions.
It doesn't. That's why people in this thread have been telling you to
do this the *right* way. Don't use two separate and distinct scripts.
Write one script, and write a module that script uses. That module
will contain one or more functions your module can call, and you can
pass arrays and hashes to and from functions arbitrarily.

By now, I guess I have learned that thanks to all the helpful people.

To summarize for other people having the same question:
Question:
'How can I pass (hand over) a variable from one perl script to another?'
Answer:
'You cannot. You can only pass scalars via the command line (or via a
temp file) by giving them as arguments when using the system command
(system 'script.pl', $scalar). But you can pass a variable to modules,
i.e. make your second script a module.'
 
J

Jürgen Exner

Markus said:
I know how to get an item out of an array but if the array contains
only one element calling the array without any arguments should give
me that element,

Why? I wouldn't expect that behaviour at all. If I assign an array to
something, then I expect to get an array again, no matter if it has one
element or many.
If I want an item from the array, then I would use whatever syntax the
programming language provides to access array elements, no matter if the
array contains one item or many.
Perl should be smart enough to do this

I seriously hope it never will because I don't want to test every single
time if my array has only one element or many.
(and I guess
it would be, were it not for the fact that @arrayname is reserved to
give me the number of elements of an array, which I did not know

Wrong, it doesn't. @arrayname gives you the _WHOLE_ array.
@foo = @bar.
Now @foo contains the same values as @bar.

Only the scalar value of @foo is it's length.
since I always used $#arrayname to get the length of an array).

But $#arrayname does not give you the length of an array, it gives you the
last index.
Which most often happens to be number of elements -1, but can be any other
value if someone tinkered with the start index $[.

jue
 

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,774
Messages
2,569,596
Members
45,143
Latest member
DewittMill
Top