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");
3
  • 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)? Commented Apr 9, 2018 at 3: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. Commented Apr 9, 2018 at 3: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. Commented Apr 9, 2018 at 3:48

3 Answers 3

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).

Sign up to request clarification or add additional context in comments.

Comments

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

1 Comment

The arguments to the script need to come after the script, not after perl. Also, as far as I can tell, 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.
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!

1 Comment

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.