Is it possible to execute a Perl script within a Stata .do file?
I have a Stata .do file in which I make some manipulations to the data set and arrange it in a certain way. Then I have a Perl script in which I take one of the variables at this point, apply a Perl package to it, and make a transformation to one of the variables. In particular, I use Perl's NYSIIS function, resulting in a very short script. After this output is provided in Perl, I'd like to continue with some additional work in Stata.
Two alternatives that come to mind but that are less desirable are:
Write Stata code to do nysiis but I prefer to use Perl's built-in function.
outsheet and save the output from the Stata .do file as a .txt for Perl. Then do the Perl script separately to get another .txt. Then read in that .txt to Stata to a new .do file and resume.
Your approach number 2 is what I use to call other programs to operate on Stata data. As Nick says, Stata won't necessarily wait for your output, unless you ask it to. You first outsheet the text file, then call the Perl script from Stata using ! to run something on the command line. Finally, have Stata periodically check for the result file, using a while loop and the sleep command so Stata isn't constantly checking.
outsheet using "perl_input.txt"
!perl my_perl_script.pl
while (1) {
capture insheet using "perl_output.txt", clear
if _rc == 0 continue, break
sleep 10000
}
!rm perl_output.txt
Here, your formatted data is saved from Stata as perl_input.txt. Next, your Perl script is run from the command line, and using a while loop, Stata checks for the output every 10 seconds (sleep takes arguments in milliseconds). When it finds the output file, it breaks out of the while loop. The last line is a good idea so that when you re-use the code you don't run the risk of using the Perl output from the last run.
I think the main issue is that although you can use the shell to call up something else, Stata is not going to wait for the results.
Start with help shell to see what is possible, but your #2 does sound easiest.
Related
I'm using MATLAB and calling an .exe via the system command.
[status,cmdout] = system(command_s);
where command_s is a command string that is formatted earlier in my script to pass all the desired options to the .exe. The .exe would normally write to a .csv file via the > redirection operator in Windows/DOS. Instead, this output is going to cmdout where I use it later in the MATLAB script. It is working correctly and as expected. I'm doing it this way so that the process just uses memory and does not write a very large file to the disk, which would then have to be read from the disk and then deleted after I'm done with it. In the end, it saves a .mat file that's usually in hundreds of KB instead of 10s/100s of MBs as the .csv file would be (some unneeded data is thrown out in the end).
The issue I'm having is since I'm dealing with large files, the executable can take a significant amount of time. I typically have to wait about 2 minutes after executing this command. In the meantime, I have no feedback to know it is progressing and that my system hasn't froze. I know I could add the & symbol to the end of my string, command_s, and run MATLAB code while this is running in the background (or asynchronously as some would say), but that brings up an external window AND makes cmdout empty - so I cannot use the output - forcing me to sit there for 2 minutes wondering each time it executes.
Is there any way to run in the background AND get the stdout from the command?
Maybe you could try system(command_s,'-echo')?
Okay, I've searched all across this site, without any luck.
Here's my problem:
I have an .exe that produces two output files when run, which it does fine when I actually use the .exe itself.
However, when I run it in MATLAB (yes it actually runs and has identical system messages just like in the command prompt), the two output files are NOT produced. I'm not sure if this is something that can be controlled using system() in MATLAB, or this is a problem with the .exe.
My code to run the .exe (it also takes an input file) is simply this:
system(['C:\MyProgram.exe ' myInputFile]);
Any tips, pointers, advice, or solutions are greatly appreciated!!!
I assume myInputfile as a string. I guess your program is NOT running, because I'd say your command is not working. Try the following:
yourCommand = strcat('c: && MyProgram.exe',{' '},myInputFile);
system( yourCommand{1} );
{' '} is neccesary, because spaces at the end of strings are ignored.
You can not just type your path into the command line, you need to define the path before and then call the function. As you cannot put all commands in a row, you need to use &&, which is like typing Enter in the command window.
I am trying to run some Perl code from Excel. If I try to pass something to the script using the shell command I am not able to return a value. I figure that if I am able to run the script in as a com module or something like that I might be able to get back a value, array or hash from the script. Does anyone know if this is possible? and if so How? Any help would be appreciated.
I am curious what is your desired result ... I mean do yo need to run a Perl script from Excel? Is it possible you could run it outside of Excel and get the same result?
If so, you could export the rows you need to perform whatever functionality the script is to do and then generate another spreadsheet using the following modules:
CPAN -> Spreadsheet::ParseExcel
CPAN -> Spreadsheet::WriteExcel
In the Perl script, write the desired return value to a temporary output file. In VB, wait until the Perl script process is complete, then open and parse the contents of that file. You could let VB choose the name of the temporary file and hand that name to the Perl script as a command line argument or an environment variable.
I have 'inherited' Matlab code (A) that uses another compiled Matlab code (B). I do not have the source of B. B requires user intervention ('Hit return to continue'), and I need to use A in a loop. I need to do something so I would not need to hit Return each and every time until the loop is done.
The command I use in the loop is:
str='!start "Code_B" /low "c:\Code_B\bin\Code.exe" r';
eval(str)
Are there any other switches that I can use to suppress the call to 'Hit return' ?
Thanks
Katto
One way you could do this is to create a batch file that:
Starts the compiled Matlab program
Waits for the program to run (fixed delay?)
Uses a utility to send the program an Enter key
There are many (free) utilities that let you send keystrokes to a program.
Instead of calling Program B, you would call this batch file.
You can create a text file, let's say autoreturn.txt, with many empty lines (just end of line characters), over the number of loops you expect. Then add redirection of input from this at the end of your string:
str='!start "Code_B" /low "c:\Code_B\bin\Code.exe" r < autoreturn.txt';
I have a quick question about creating files with perl and executing them. I wanted to know if it was possible to generate a file using perl (I actually need a .bat script) and then execute this file internally to the program. I know I can create files, and I have with perl, however, I'm wanting to do this internally to the program. So, what I want it to do is actually create a batch script internally to the program (no file is actually written to the disk, everything remains in memory, or the perl program), and then once it completes the writing of the file, I'd like to be able to actually execute this file, and then discard the file it just wrote. I'm basically trying to have it create a batch script on the fly, so that I can just have output text files from the output of the script, rather than creating the batch script on disk, then executing it, and then deleting the batch file from disk when its done.
Can this be done and how would I go about doing this?
Regards,
Drew
Do you really need a batch script? Perhaps everything you want to do can be done directly from Perl or invoked directly by Perl via its system command.
If a batch script is essential, what's wrong with creating a temporary file for the script and then executing it with system? See File::Temp, which will even delete the temporary file automatically after you are done.
If the virtual-batch-file strategy is unavoidable, you might be able to leverage the /C and maybe /S options of cmd. Something like this:
use strict;
use warnings;
my #batch_commands = (
'dir',
q{echo "Make sure quoting isn't busted"},
'ipconfig',
);
# Use & or &&, depending on your needs. Run `cmd /?` for details.
my $virtual_bat_file = join " &\n", #batch_commands;
system "cmd /C $virtual_bat_file";
But this feels very wrong. There has to be a better way to accomplish whatever the larger goal of your application is. By the way, when you run cmd /? to learn about /C, /S, and & vs. &&, you'll quickly appreciate how terrible it is in the Land of Batch. Stay away if at all possible.
open the file; create the contents; close the file; execute the file (with system(), for example); remove the file.