3

I'm writing a Perl program that must run a few Perl scripts multiple times on different inputs.

The scripts I'm trying to use are count.pl and statistic.pl from Text::NSP. I didn't write those myself so I don't want to try and refactor them into a module.

I looked at a similar question and figured out how to use the system method from IPC::System::Simple.

However, I want to make use of the named arguments in count.pl and statistic.pl. I haven't yet figured out how to do this. This is my current code:

system($^X, token="valid_tokens.txt", "/Users/cat/perl5/bin/statistic.pl", "ll.pm", "lab01_jav_bigrams.ll",
"/Users/cat/Perl_scripts/214_Final_project/lab01_java_bigrams.cnt");

And this is the error I get:

Can't modify constant item in scalar assignment at ngram_calcs.PL line 22, near ""valid_tokens.txt"," Bareword "token" not allowed while "strict subs" in use at ngram_calcs.PL line 22.

It's worth noting that the code worked fine until I added the named argument. How do I supply a named argument to IPC::System::Simple? Or is there a better way to do what I'm trying to do?

Edit: Thanks, Haukex, I did have the wrong parameters, and using "--token=valid_tokens.txt" worked.

Even though the problem is solved, I'll share more context so that other people who see can benefit. On the commmand line I would type this:

count.pl -token validtokens.txt lab01_java_bigrams.cnt Users/cat/CS214/lab01_java.txt
statistic.pl -score 6.63 ll.pm lab01_java.ll lab01_java_bigrams.cnt

This is the correct perl code:

system($^X, "/Users/cat/perl5/bin/count.pl", "--token=valid_tokens.txt", "lab01_java_bigrams.cnt", $filename);
system($^X, "/Users/cat/perl5/bin/statistic.pl", "--score=6.63", "ll.pm", "lab01_java_bigrams.ll", "/Users/cat/Perl_scripts/214_Final_project/lab01_java_bigrams.cnt");
  • What is `token="valid_tokens.txt"`? I wouldn't expect that to be a valid use of "named arguments." How do you invoke that program from the command line? You can pass arguments to a program only in a way it's written to take them. As for the error you show, what is the relevant code in "_ngram_calcs.PL_" (simplified if need be)? – zdim Apr 09 '18 at 03:39
  • You are not "_supplying a named argument to IPC::System::Simple_". The module provides commands that replace the `system` builtin and which supply to that program what is given to them. – zdim Apr 09 '18 at 03:45
  • I suggest that you edit the question and show how those programs are invoked on their own, from the command line, without the script you are writing. You'd also want to show the code of the script you are writing. – zdim Apr 09 '18 at 03:48

3 Answers3

4

I am confused about your system invocation. Looking at the sources of statistic.pl and count.pl, it seems that only the latter takes a token argument, but you don't seem to be running count.pl. $^X is the currently running Perl interpreter, which would normally be followed by any arguments to the interpreter, then the name of the script, then any arguments to the script, so placing the token argument before the script doesn't make sense to me.

If you are for example trying to pipe the output of count.pl into statistic.pl, you'll have to explain further, because that is something that IPC::System::Simple can't handle (at least not without invoking the shell, which I would recommend against), and you'd need a more advanced module like IPC::Run. For now, I will assume you want to pass the token parameter to a script that supports it.

Command line arguments are just strings. If from a *NIX shell you were to write something like ./script.pl token="test file" foo bar, then the shell would take over the interpretation of white space and quoting. script.pl will get a list of strings like ("token=test file", "foo", "bar") (note how the shell took care of the quotes there).

This list of strings is what you need to pass to system, which is not necessarily the same as what you would type on the command line. It is up to the called program to interpret those arguments. The two scripts you are running use Getopt::Long, and the named arguments need to be prefixed by two dashes. So something like this should work:

system($^X, "/Users/cat/perl5/bin/count.pl", "--token=valid_tokens.txt", ...);

As for how to pass arguments that include special characters like quotes (which does not apply in this case), there are various syntaxes in Perl: "--foo=\"bar\"", '--foo="bar"', or q{--foo="bar"} (see Quote and Quote-like Operators).

haukex
  • 2,973
  • 9
  • 21
2

Assuming your call to statistic.pl is broadly correct, the parameters to system need to look like this

system($^X,
    "/Users/cat/perl5/bin/statistic.pl",
    qq/token="valid_tokens.txt"/,
    "ll.pm",
    "lab01_jav_bigrams.ll",
    "/Users/cat/Perl_scripts/214_Final_project/lab01_java_bigrams.cnt"
);

i.e. all parameters belong after the program file, and the whole of the named parameter string must be enclosed in quotes

Please read the comment from haukex below for another potential error

Borodin
  • 126,100
  • 9
  • 70
  • 144
  • The arguments to the script need to come after the script, not after `perl`. Also, [as far as I can tell](https://stackoverflow.com/a/49728446/9300627), `token` needs two dashes and including the quotes in the argument would cause the target script to try and open a filename *including* those quotes. – haukex Apr 09 '18 at 08:24
0

Can you try this format?

system('/Users/cat/perl5/bin/statistic.pl  --token valid_tokens.txt  ll.pm  lab01_jav_bigrams.ll  /Users/cat/Perl_scripts/214_Final_project/lab01_java_bigrams.cnt');

But I check the source of the CPAN module, seems token is an option for count.pl, but not statistic.pl.

Anyway, any options can be specified similar to --token valid_tokens.txt.

Hope this help!

Shuwn Yuan Tee
  • 5,578
  • 6
  • 28
  • 42
  • 3
    `system` with a single string argument has the disadvantage that it may cause the command to be passed through the default shell, causing shell metacharacters to make a difference. Unless those interpolations are specifically desired, the multi-argument form of `system` is safer. – haukex Apr 09 '18 at 07:30