Embedded Perl script in Linux shell [duplicate] - linux

This question already has an answer here:
perl inside bash: How to call perl on a script saved in a string
(1 answer)
Closed 7 years ago.
Can I invoke Perl script from Unix shell? For example I have bash script in form like:
#!/bin/sh
echo This is bash
i=12
echo $i
perl <<__HERE__
print "This is perl\n";
my \$i = $i;
print ++\$i . "\n";
echo This is bash again
echo $i
Above is just an example.
Is it possible to pass variables from bash to script? Hope I expressed myself correctly and properly. I need to call Perl script which will take values from bash script and use them and then return processed results.

The problem is the dollar signs need escaped. It makes for an ugly, error prone Perl script. Use environmental variables.
#!/bin/bash
export i=12
readarray results < <(perl <<-'__HERE__'
my $i = $ENV{'i'};
print "$i\n";
$i += 1;
print "$i\n";
__HERE__
)
for r in "${results[#]}"; do echo $r; done
The quotes around HERE prevents bash from doing variable substitution. The "-" allows the here is document to be indented it tabs.
While this is a nice exercise in the finer points of Bash, why not just code in Perl or Bash alone? Bash does regular expressions, arrays, etc. And Perl can do everything Bash can.

This is a way to call a Perl script in Shell script. Make sure Perl script is executable and the first line is #!/usr/bin/perl.
#!/bin/sh
/path/to/perlscript/scriptName.pl arg1 arg2
arg1 arg2 .. are the arguments if you need to pass any.
You can set the PATH and call the script like this:
#!/bin/sh
PATH=/path/to/perlscript/
${PATH}test.pl

Related

Writing variables to file with bash

I'm trying to configure a file with a bash script. And the variables in the bash script are not written in file as it is written in script.
Ex:
#!/bin/bash
printf "%s" "template("$DATE\t$HOST\t$PRIORITY\t$MSG\n")" >> /file.txt
exit 0
This results to template('tttn') instead of template("$DATE\t$HOST\t$PRIORITY\t$MSG\n in file.
How do I write in the script so that the result is template("$DATE\t$HOST\t$PRIORITY\t$MSG\n in the configured file?
Is it possible to write variable as it looks in script to file?
Enclose the strings you want to write within single quotes to avoid variable replacement.
> FOO=bar
> echo "$FOO"
bar
> echo '$FOO'
$FOO
>
Using printf in any shell script is uncommon, just use echo with the -e option.
It allows you to use ANSI C metacharacters, like \t or \n. The \n at the end however isn't necessary, as echo will add one itself.
echo -e "template(${DATE}\t${HOST}\t${PRIORITY}\t${MSG})" >> file.txt
The problem with what you've written is, that ANSI C metacharacters, like \t can only be used in the first parameter to printf.
So it would have to be something like:
printf 'template(%s\t%s\t%s\t%s)\n' ${DATE} ${HOST} ${PRIORITY} ${MSG} >> file.txt
But I hope we both agree, that this is very hard on the eyes.
There are several escaping issues and the power of printf has not been used, try
printf 'template(%s\t%s\t%s\t%s)\n' "${DATE}" "${HOST}" "${PRIORITY}" "${MSG}" >> file.txt
Reasons for this separate answer:
The accepted answer does not fit the title of the question (see comment).
The post with the right answer
contains wrong claims about echo vs printf as of this post and
is not robust against whitespace in the values.
The edit queue is full at the moment.

backticks `cat filename` failed, file content is several commands

My system is CentOS 6.5
When I want to use backtick to run the commands in filename, i got the result below:
the file's content is below:
[liu-uil#~ 15:54:16]$cat test
echo 1;
echo 2;
echo 3;
[liu-uil#~ 15:54:18]$`cat test`
1; echo 2; echo 3;
[liu-uil#~ 15:54:24]$
the commands after the first echo are all treated as text plain, I don't know why? Could somebody kindly explain this to me? Thank you very much!
Command substitution is one of the expansions. Expansions happen when the command line was already split into commands, it's too late to create new commands.
You can use
eval `cat 1`
to call the shell parser again to split the string into commands and run them.
Only the first word in the result of a backtick command is interpreted as a command. Remaining text is the argument list.
If you want to run commands in a file, you don't need backticks, you need the dot (.) command:
[liu-uil#~ 15:54:16]$. test

Return variable from node.js to sh script

Is it possible to execute node.js app from .sh script, return some variable and continue the .sh script?
Something like:
#!/bin/sh
SOME_VARIABLE = node app.js
echo ${SOME_VARIABLE}
Firstly, ensure you're using bash, not sh, as there are significant differences in functionality between the two.
One simple solution is command substitution, although be aware that trailing newlines in the command output will be stripped. Also, when echoing, to protect the contents of the variable (such as spaces and glob characters) from metaprocessing by the shell, you have to double-quote it:
#!/bin/bash
output=$(node app.js);
echo "$output";
Another solution is process substitution in more recent versions of bash. You could even collect the output as an array of lines in this case:
#!/bin/bash
exec 3< <(node app.js);
lines=();
while read -r; do lines+=("$REPLY"); done <&3;
exec 3<&-;
echo "${lines[#]}";

shell string bad substitution

I'm new to shell programming. I intend to get directory name after zip file was extracted. The print statement of it is
$test.sh helloworld.zip
helloworld
Let's take a look at test.sh:
#! /bin/sh
length=echo `expr index "$1" .zip`
a=$1
echo $(a:0:length}
However I got the Bad substitution error from the compiler.
And when I mention about 'shell'.I just talking about shell for I don't know the difference between bash or the others.I just using Ubuntu 10.04 and using the terminal. (I am using bash.)
If your shell is a sufficiently recent version of bash, that parameter expansion notation should work.
In many other shells, it will not work, and a bad substitution error is the way the shell says 'You asked for a parameter substitution but it does not make sense to me'.
Also, given the script:
#! /bin/sh
length=echo `expr index "$1" .zip`
a=$1
echo $(a:0:length}
The second line exports variable length with value echo for the command that is generated by running expr index "$1" .zip. It does not assign to length. That should be just:
length=$(expr index "${1:?}" .zip)
where the ${1:?} notation generates an error if $1 is not set (if the script is invoked with no arguments).
The last line should be:
echo ${a:0:$length}
Note that if $1 holds filename.zip, the output of expr index $1 .zip is 2, because the letter i appears at index 2 in filename.zip. If the intention is to get the base name of the file without the .zip extension, then the classic way to do it is:
base=$(basename $1 .zip)
and the more modern way is:
base=${1%.zip}
There is a difference; if the name is /path/to/filename.zip, the classic output is filename and the modern one is /path/to/filename. You can get the classic output with:
base=${1%.zip}
base=${base##*/}
Or, in the classic version, you can get the path with:
base=$(dirname $1)/$(basename $1 .zip)`.)
If the file names can contain spaces, you need to think about using double quotes, especially in the invocations of basename and dirname.
Try running it with bash.
bash test.sh helloworld.zip
-likewise-
"try changing the first line to #!/bin/bash" as comment-answered by – #shellter
Try that in bash :
echo $1
len=$(wc -c <<< "$1")
a="${1}.zip"
echo ${a:0:$len}
Adapt it to fit your needs.

Accessing shell variable in a Perl program

I have this Perl script:
#!/usr/bin/perl
$var = `ls -l \$ddd` ;
print $var, "\n";
And ddd is a shell variable
$ echo "$ddd"
arraytest.pl
When I execute the Perl script I get a listing of all files in the directory instead of just one file, whose file name is contained in shell variable $ddd.
Whats happening here ? Note that I am escaping $ddd in backticks in the Perl script.
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}`;
You forgot to export ddd:
Mark each name to be passed to child processes in the environment.
So ddd is not automatically available to child processes.
The hash %ENV contains your current environment.
$var = `ls -l $ENV{ddd}`;
/edit - it works, checked, of course ddd need to be exported before running script
export ddd='arraytest.pl'
perl script.pl

Resources