Running Perl within another Perl - perl

I have an existing perl script which I run like this in UNIX.
echo $query | runQuery.pl -a -f,
It runs a query and returns rows with -f delimiter which in above case would be ",".
I want to run the same command in another perl script where I have already defined $query and store the results in an array (#results).
I was not able to get system() work properly. Please assist.
Thanks and Regards,
-Tushar

Something like this ought to work for you:
my $arguments = '-a -f,';
my #results = `echo $query | runQuery.pl $arguments`;

Related

Filename on Windows that works with pipes in batch or PowerShell

I have a Linux shell script with a line that looks like this:
./cmd1 -o /dev/stdout | ./cmd2
I'm trying to port it to Windows. I don't care whether it ends up as a batch file or a PowerShell script. I tried this in a batch file at first:
cmd1 -o con | cmd2
But this sent the output of cmd1 to the console, and cmd2 didn't receive any input. The problem is that con is the equivalent of /dev/tty, not /dev/stdout. What output filename can I pass that will be the equivalent of /dev/stdout, or at least close enough to make the pipe work?
Can you try this?
./cmd1 -o /dev/stdout | ./cmd2 -i /dev/stdin
The equivalent command on Windows using batch or PowerShell would be:
cmd1 -o - | cmd2 -i -
you can pipe it to foreach-object
cmd1 | % { cmd2 $_ }
the $_ stands for the result of the output that is sent to the next command, sometimes with certain programs you may need to use write-output (cmd1) | % {cmd2} but the first one should suffice for what you want to do.
You can also store the output of the first command like this
$var = cmd1
or like this
cmd1 > $var
If you can specify the file output and file input for both commands you could try this.
$file = "C:\file"
cmd1 -o $file ; cmd2 -i $file
but as phuclv commented, there's no stdout equivalents in Windows by default

How to cat dynamic filename with date format

I can use the command to devices id from /var/log/20140522.device.log.
Here is my command.
for i in `cat /var/log/20140522.device.log`; do echo ---$i; done
Now I want to make it by daily cron job, but it is not working.
for i in `cat /var/log/`/bin/date +%Y%m%d`.device.log`; do echo ---$i; done
Is it possible to put cat and date in one line?
Yes; you can use cat and date on the same line using command substution.
for file in $(cat /var/log/$(date +'%Y%m%d').device.log); do echo ----$file; done
Using the $(…) notation makes that nested operation much simpler than the back-tick notation:
for file in `cat /var/log/\`date +'%Y%m%d'\`.device.log`; do echo ----$file; done
You don't have to think as hard about where backslash escapes are needed.
Also, in Bash, you can avoid the use of cat with:
for file in $(</var/log/$(date +'%Y%m%d').device.log); do echo ----$file; done
A $ character need to be added as follows:
for i in `cat "/var/log/$(date +"%Y%m%d").device.log"`

Running the /usr/bin/time from perl [duplicate]

This question already has an answer here:
How do I use backticks to capture the elapsed time output from time(1)?
(1 answer)
Closed 9 years ago.
I'm trying to do some very-rough benchmarking and so I'd like to run the time command from my script. I have the following:
#!/usr/bin/perl
use strict;
my $command = "/usr/bin/time -f \"%U,%S,%E,%P,%K,%M\" ...";
my $stats = `$command`;
print "stats: $stats\n";
Unfortunately, it looks like the result of the command is never assigned to $stats. When I execute the script, I get something like the following:
0.15,0.03,0:00.44,43%,0,143808
stats:
So it looks like it runs the time command successfully, but prints out the value to STDOUT instead of assigning the value to $stats. When I use another command, like ls, it seems to work as expected. What am I doing wrong here?
time prints to stderr.
$ /usr/bin/time -f "%U,%S,%E,%P,%K,%M" echo foo >/dev/null
0.00,0.00,0:00.03,10%,0,2352
$ /usr/bin/time -f "%U,%S,%E,%P,%K,%M" echo foo >/dev/null 2>/dev/null
$
So just add 2>&1 to your command.
time writes to standard error, so you need to redirect it to standard output to capture it with Perl's backticks
my $command = "/usr/bin/time -f \"%U,%S,%E,%P,%K,%M\" ... 2>&1";

storing output of perl command into a variable

This works fine
system("perl -c C:/Users/mytest/scripts/file_name.pm")
This command gives many lines of output in cygwin and a single syntak ok line in centos. since ill be using cygwin, what am trying to do is to get this output into a variable and use it later in my program. How can i do it?
Thanks in advance for your time.
Instead of system, use backticks:
my $output = `perl -c C:/Users/mytest/scripts/file_name.pm`;
if you want to also include STDERR output, use:
my $output = `perl -c C:/Users/mytest/scripts/file_name.pm 2>&1`;

Pulling hostname from TNS entry

I am working on a script that will need to determine which node a db being used by a local app is running on. I've been trying to use this as a chance to force myself to learn awk/sed and have a test script to test the statements. It's working off a copy of the tnsnames.ora file I have moved to the home folder the script is located in.
Here is a valid tnsnames.ora stanza:
(
DESCRIPTION = (
ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP) (Host=iplab)(Port=1521))
)
(CONNECT_DATA=(SID=spurs1))
)
After doing some research and getting the awk expression to pull the tns entry to $host I came up with the below script but it doesn't seem to work.
#!/bin/ksh
db=spurs
host=$(awk -v db=$db "/${db}/ {for(i=1; i<=5; i++) {getline; print}}" tnsnames.ora)
echo $host
host= $host | sed 's/Host\s=\s\([a-z]+[0-9]?\)/\1/'
echo $host
When I run it the awk statement I get the following:
(DESCRIPTION = (ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP) (Host=hostname)(Port=1521))) (CONNECT_DATA=(SID=spurs1)) )
./tns.ksh: line 6: (DESCRIPTION: not found
(DESCRIPTION = (ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP) (Host=hostname)(Port=1521))) (CONNECT_DATA=(SID=spurs1)) )
From what I have seen reading tutorials and forums I think sed is setup correctly and should be setting $host to one or more lowercase letters followed by 0 or 1 numbers after Host = . Since (DESCRIPTION is the start of $host before and after the sed statement I'm not sure how it isn't finding it, an
This worked for me:
tnsping $db | grep HOST | cut -d\ -f 14 | sed 's/).*//g'
On my system I can use this to get the host as long as the host name doesn't have an equals sign (or the actual literal word HOST in the name of the host):
echo $TNS_STRING | sed 's/.HOST//g' | sed 's/).//g' | sed 's/=//g' | sed 's/\s*//g'
Your value for $host is likely a multiline value, so you need to quote it anyplace you use it, i.e.
host=$(awk -v db=$db "/${db}/ {for(i=1; i<=5; i++) {getline; print}}" tnsnames.ora)
echo "$host"
You also need to capture the output (using command-substitution) via $(...)
host=$(echo "$host" | sed 's/Host\s=\s\([a-z]+[0-9]?\)/\1/')
echo "$host"
(and echo it), so it can be processed by sed
Revise
host=$(echo $host | sed 's/.*Host=//; s/).*$//)
echo "$host"
I've switched back to just $host, without the dbl-quotes, as you don't want the linebreaks in the data. Now it is all one big string, and the regex, strips every upto host=, and then strips everything after the first remaining ) char.
If you still get error messages, I don't have access to a tnsnames.ora record, so please edit your query to include a valid record.
I hope this helps.
you may be better relying on the output of tnsping instead of parsing the file: tnsping appears to emit the description on one line:
host=$(
tnsping $db | while read line; do
if [[ "$line" == *HOST* ]]; then
s=${line#*HOST=}; s=${s%%)*}; echo "$s"; break
fi
done
)
This might work for you:
db=spurs
host=$(sed '/^(/,/^)/!d;/^(/{h;d};H;/^)/!d;g;/'"$db"'/!d;s/.*Host=\([^)]*\).*/\1/' tnsnames.ora)
Tested Code:
OIFS=$IFS;
IFS="(";
tns=`tnsping TNS_ALIAS`
tns_arr=($tns);
tns_info=(`(for ((i=0; i<${#tns_arr[#]}; ++i)); do echo "${tns_arr[$i]/)/}"; done)| grep 'HOST\|PORT'|sed 's/)//g'|sed 's/ //g'`)
for ((i=0; i<${#tns_info[#]}; ++i)); do eval "export ${tns_info[$i]}"; done
echo "host:" $HOST
echo "port:" $PORT
IFS=$OIFS;