Ordinarily I would invoke Perl and supply required arguments from within a bash script simply using:
perl script.pl arg1
However there are cases when I want to store both the perl script directory and the arguments in bash variables:
PERLDIR = "/example/directory/script.pl"
ARG1 = "40"
When trying to call the perl script using:
perl "$PERLDIR"
It works, however when trying to provide the argument i'm not sure of the syntax to utilise. If I use:
perl "$PERLDIR $ARG1" it'll attempt to open the directory:
/example/directory/script.pl 40
And throw an error.
Is there a way to do this and if so, how?
You should use:
perl "$PERLDIR" "$ARG1"
When you use many variables in one string enclosed with " it becomes one argument.
Related
Beginner in bash and makefiles here. I have a course where we need to create a makefile where each rule calls one of the already compiled programs. All of the compiled programs take a command line argument. As the arguments can be quite large and mostly consists of the same character in a row (for example AAAAAAA) I made a script that uses python to print the argument. Example:
#!/bin/bash
python -c 'print "A"*1000 + "Q"*200'
I am wondering how to create the rule in the makefile so that the output of the above script will be passed as the command line argument. Essentially like this:
test:
./schoolprogram ./myprogram.sh
So when make test is executed then ./schoolprogram should be run with the argument 1000 A's followed by 200 Q's and not the literal string "./myprogram.sh".
I don't know why you have a script that does nothing but invoke python; why not just run python directly?
In any event, this isn't really a makefile question it's mostly a shell question. When writing makefile recipes, the best way is to get the command you want to run working at your shell prompt, then take that same command (with one small tweak) and put it into your makefile.
In the shell, you can use either $(...) or backticks (an older style) to run a command and replace it with the output of that command. So you can run this:
$ ./schoolprogram $(./myprogram.sh)
or more easily:
$ ./schoolprogram $(python -c 'print "A"*1000 + "Q"*200')
Now when you take a command and put it into a makefile recipe, the thing you have to remember is that the $ character is special to make, so if you want a $ to be passed to your command you have to escape it by doubling it, $$. So you'd write:
test:
./schoolprogram $$(./myprogram.sh)
or equivalently:
test:
./schoolprogram $$(python -c 'print "A"*1000 + "Q"*200')
In the terminal, I can access variable $LINES:
$ echo $LINES
39
Running Perl script like so:
#!/usr/bin/env perl
use strict; use warnings;
my $cmd = q|echo $LINES|;
my $lines = `$cmd`;
print "lines: $lines\n";
gives output: lines:. I tried also accessing %ENV, but it does not contain this particular key.
How could I access shell variable $LINES from a 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.
The export and declare -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).
I am learning Perl and Shell scripting and of the challenges I was given is to write a shell script that takes a csv file as an argument and then have that shell script run my perl script (test.pl). I can't seem to get the proper syntax down and I have terminate every time because it hangs up my terminal.
For example shell script is test.sh
#/bin/bash
./test.pl $i`
on my terminal I write type out
test.sh testfile.csv
Ultimately I want the test file to be read by my perl script so it can run.
I think your error comes from the $i` part.
First the trailing backquote is probably a typo and should raise a syntax error. Second, the i variable is not defined, so $i resolve to an empty string. As it is not quoted, shell will omit it and call test.pl without any arguments... Thus your terminal is probably hanging because your perl script is waiting for input.
As #fra suggested, you should use $1 instead of $i, hence passing the first argument passed to your bash script, to your perl script.
Depending on your perl script (shebang, execution write) you may or may not call the perl executable manually.
i have the following issue:
I try to start a perl script from the windows scheduler through cygwin
Steps i do:
Call process.bat file
In the process.bat i call bash with the parameter for the perl script
Symptoms:
If i call "perl scriptpath" directly from cygwin it works like a charm
If i call the script from the windows cmd with bash it will not work.
Command: C:\cygwin\bin\bash.exe --login /cygdrive/c/scripts/testscript.pl
It prints the following:
Line 3: use: command not found
Line 4: use: command not found
Can't find file Test
Script:
#!/usr/bin/perl
use strict;
use warnings;
print "Test";
Probably i'm making only a small mistake and cannot see it. It seems to interpret it with the windows cmd instead of the perl.
The parameter passed to bash will be treated as a Bash script, not a Perl script. There is no reason to use Bash in this case - just invoke Perl directly:
C:\cygwin\bin\perl.exe /cygdrive/c/scripts/testscript.pl
If you really want to do it your way - calling a cmd script which calls a Bash script which calls a Perl script - then you would need to write a Bash script to invoke your Perl script:
#!/bin/sh
/cygdrive/c/scripts/testscript.pl
And pass that Bash script as the parameter when you invoke bash.
You might like to use option -c to have bash execute a command, like this:
C:\cygwin\bin\bash.exe --login -c /cygdrive/c/scripts/testscript.pl
From the bash's man-page:
-c string
If the -c option is present, then commands are read from string. If there are arguments after the string, they are assigned to the positional parameters, starting with $0.
i have unix shell script which is need to be run like below
test_sh XYZ=KLMN
the content of the script is
#!/bin/ksh
echo $XYZ
for using the value of XYZ i have do set -k before i run the script.
is there a way where i can do this without doint set -k before running the script. or is there something that i can do in the script where i can use value of the parameter given while running the script in the below way
test_sh XYZ=KLMN
i am using ksh.
Any help is appreciated.
How about running this?
XYZ=KLMN ./test_sh //running from directory where test_sh is
If your script needs no other arguments, a quick and dirty way do to it is to put
eval "$#"
at the start of your script. This will evaluate the command line arguments as shell commands. If those commands are to assign a shell/environment variable, then that's what it will do.
It's quick-and-dirty since anything could be put on the command line, causing problems from a syntax error to a bad security hole (if the script is trusted).
I'm not sure if "$#" means the same in ksh as it does in bash - using just $* (without quotes) would work too, but is even dirtier.
It looks like you are trying to use the environment variable "INSTANCE" in your script.
For that, the environment variable must be set in advance of executing your script. Using the "set" command sets exportable environment variables. Incidentally, my version of ksh dates from 1993 and the "-k" option was obsolete back then.
To set an environment variable so that it is exported into spawned shells, simply use the "export" command like so:
export INSTANCE='whatever you want to put here'
If you want to use a positional parameter for your script -- that is have the "KLMN" value accessed within your script, and assuming it is the first parameter, then you do the following in your script:
#!/bin/ksh
echo $1
You can also assign the positional parameter to a local variable for later use in your script like so:
#!/bin/ksh
param_one=$1
echo $param_one
You can call this with:
test_sh KLMN
Note that the spacing in the assignment is important -- do not use spaces.
I am tring this option
#!/bin/ksh
echo $1
awk '{FS="=";print $2}' $1
and on the command line
test_sh INSTANCE=LSN_MUM
but awk is failing.is there any problem over here?
Probably #!/bin/ksh -k will work (untested).