Accessing shell variable in a Perl program
The variable $ddd
isn't set *in the shell that you invoke from your Perl script.
Ordinary shell variables are not inherited by subprocesses. Environment variables are.
If you want this to work, you'll need to do one of the following in your shell before invoking your Perl script:
ddd=arraytest.pl ; export ddd # sh
export ddd=arraytest.pl # bash, ksh, zsh
setenv ddd arraytest.pl # csh, tcsh
This will make the environment variable $ddd
visible from your Perl script. But then it probably makes more sense to refer to it as $ENV{ddd}
, rather than passing the literal string '$ddd'
to the shell and letting it expand it:
$var = `ls -l $ENV{ddd}`;
How could I access shell variable from Perl script?
From bash manual:
When a program is invoked it is given an array of strings called the
environment. [...] The shell provides several ways to manipulate the
environment. On invocation, the shell scans its own environment and
creates a parameter for each name found, automatically marking it for
export to child processes. Executed commands inherit the environment.
Theexport
anddeclare -x
commands allow parameters and functions to
be added to and deleted from the environment.
So (assuming a Bash shell) using:
export LINES
will make the variable $LINES
available from within a Perl script startet from the Shell (using $ENV{LINES}
from the Perl script).
How to use shell variables in perl command call in a bash shell script?
The same way you pass values to any other program: Pass it as an arg. (You might be tempted to generate Perl code, but that's a bad idea.)
Dt=$( perl -MPOSIX -e'print strftime $ARGV[0], localtime time-86400;' -- "$myDate" )
Note that code doesn't always return yesterday's date (since not all days have 86400 seconds). For that, you'd want
Dt=$( perl -MPOSIX -e'my @d = localtime time-86400; --$d[4]; print strftime $ARGV[0], @d;' -- "$myDate" )
or
Dt=$( perl -MDateTime -e'print DateTime->today(time_zone => "local")->subtract(days => 1)->strftime($ARGV[0]);' -- "$myDate" )
or simply
Dt=$( date --date='1 day ago' +"$myDate" )
Using Bash environment variables from within a Perl script?
There are two queries here, on use of Bash variables and on running external commands.
There is the %ENV
hash in Perl, with environment variables
perl -wE'say $ENV{PWD}'
However, you are often better off getting the equivalent within the script, as things may have a subtly different meaning for the script or change as the script runs.
More importantly, using shell commands exposes you to all kinds of potential problems with quoting, shell injection, and interpretation. For instance, the command you show is dangerous, as outlined in Charles Duffy comment. It is in principle better to use Perl's rich functionality. See for example
Executing system commands safely while coding in Perl and
Using system commands in Perl instead of built in
libraries/functions
for a sober, and detailed, account of advantages.
In case you do need to run external commands, it is best to avoid the shell altogether, for example by using the multi-argument form of system. If you need the output of the command as well there are various modules in Perl that provide that. See links below.
If you also need to use the shell's capabilities, instead of quoting everything just right in order for the shell to receive what it needs better use a ready tool like String::ShellQuote.
Some examples:
How to use both pipes and prevent shell expansion in perl system function?
Perl is respecting '<' as a regular character rather an output redirection
How to pipe the content of a variable as STDIN in a qx{} statement in Perl?
Perl system command with multiple parameters output to file.
Note that qx operator (backticks) uses /bin/sh
, which may or may not get relegated to Bash. So if you want Bash you'll need system('/bin/bash', '-c', @cmd)
. See the links with examples.
Here is a full example related to the objective behind the question.
Your program's working directory may be other than expected depending on how it's started. For one, it changes after chdir
. I don't know your exact intent with PWD
, but in Perl there are core Cwd::cwd
and FindBin with $RealBin
, for the current working directory and for the directory where the script resides (generally different things).
To create a symbolic link to $path
, with the relative path following the current working directory
use warnings;
use strict;
use Cwd qw(cwd);
my $cwd = cwd;
my $path = '/first/path';
symlink($path, "$cwd/second/path") or die "Can't make a symlink: $!";
If the path is meant to be the script's location use $RealBin
from FindBin
instead of cwd
.
Note that with symlink you cannot pass a directory instead of a link name. See this page.
How do I pass $SHELL variable into a perl search and replace
For an example like the following:
$ value=$(uname -r)
$ perl -e 'print "$value"'
When we run Perl to execute our code here we are not sending the contents of the shell variable $value to Perl. We are sending the literal string '$value', which Perl will then try and print the Perl variable $value, which does not exist.
Here are two ways that you could correct this.
The first would be to wrap your Perl code in double quotes instead of single quotes so that $value becomes the contents of the shell variable $value instead of the literal string '$value' when sent to Perl:
$ value=$(uname -r)
$ perl -e "print '$value'"
3.13.9-generic
However when using this method if you have Perl variables along with this shell variable you will need to 'escape' the Perl variables or you'll get an error like this:
$ value=$(uname -r)
$ perl -e "$example = 'test'; print \"$value $example\";"
syntax error at -e line 1, near "="
Using \'s will correct this:
$ value=$(uname -r)
$ perl -e "\$example = 'test'; print \"$value \$example\";"
3.13.9-generic test
Secondarily, you can avoid changing the single quotes to double quotes by exporting "value" to the environment, and then accessing it through the %ENV hash already available inside your Perl program (http://perldoc.perl.org/Env.html). For example:
$ export value=$(uname -r)
$ perl -e 'print "$ENV{value}\n"'
3.13.9-generic
Be mindful of your environment that you do not accidentally overwrite some needed environment variable. Using a naming convention very specific to your work can help:
$ export MYPROGRAMNAME_KERNEL_VERSION=$(uname -r)
$ perl -e 'print "$ENV{MYPROGRAMNAME_KERNEL_VERSION}\n"'
3.13.9-generic
printenv
on most Linux systems will show you the current established environment variables. You could also just use Perl to inspect %ENV.
using environment variable in the perl script
$GATE
in a double quoted string will be considered a Perl variable. If you want to use an environment variable, you can use the %ENV
hash:
system ("bsub xyz +OPTIONS_GATE=$ENV{GATE}")
Alternatively, you can escape the dollar sign so Perl does not treat $GATE
as a Perl variable:
system ("bsub xyz +OPTIONS_GATE=\$GATE")
Or use a single quoted string, which does not interpolate variables:
system ('bsub xyz +OPTIONS_GATE=$GATE')
Note that if you had used
use strict;
use warnings;
It would have told you about this error. strict
would have said:
Global symbol "$GATE" requires explicit package name
Execution of script.pl aborted due to compilation errors.
And warnings
would have said:
Name "main::GATE" used only once: possible typo at script.pl line 12.
Use of uninitialized value $GATE in string at script.pl line 12.
When you do not use use strict; use warnings;
your errors are not removed, they are only hidden from you, so that they are harder to find. Therefore, always use these two pragmas.
Related Topics
Understanding Sendfile() and Splice()
Implementing Poll in a Linux Kernel Module
Deduplicate Git Forks on a Server
Get Utf-8 Input with X11 Display
Performance - Multithreaded or Multiprocess Applications
How to Setup a Periodic Timer Callback in a Linux Kernel Module
How to Translate Linux Keycodes from /Dev/Input/Event* to Ascii in Perl
Automated Test Tools for Linux/Ncurses
Linux - Without Hardware Soundcard, Capture Audio Playback, and Record It to File
How to Start Redis-Server on a Different Port Than the Default Port 6379 in Ubuntu
Populate a Ms Access Database in Linux
Using Curl in a Bash Script and Getting Curl: (3) Illegal Characters Found in Url
Print on Terminal and into File Simultaneously