Can't execute command in Perl script - perl

first of all, i'm totally new to Perl and i need to remove a string from a file.
Code i have:
#!/usr/bin/perl -w
use warnings;
use strict;
my $server_a = 'xxx.test.ch';
print "$server_a\n";
perl -pli -e "s/$server_a//" '/Users/user/Downloads/exports';
When i execute this script i get this error:
syntax error at nfs_test.sh line 9, near "pli -e "
Execution of nfs_test.sh aborted due to compilation errors.
i cant find whats wrong, i hope you can help me.

#! /usr/bin/perl
use warnings;
use strict;
#ARGV = '/Users/user/Downloads/exports';
$^I = '~';
my $server_a = quotemeta 'xxx.test.ch';
s/$server_a//, print while <>;
The #ARGV array contains the arguments, it's iterated by the diamond operator.
$^I is equivalent to the -i option.
You probably need quotemeta, as you don't mean "anything but newline" by dots in the server name.

Related

How to pass command line arguments along with perl modules using perl?

I treid one of my previous example to pass input and output files via command line arguments using perl?
Previous example:
[Is it possible to add the file out in the File::Find::Rule using perl?
code which i tried to add input and output file as command line arguments:(generate.pl).I got struck how to include command line arguments to read and copy the files along with perl modules.
use strict;
use warnings 'all';
use CGI qw(:all);
#generate the user file arguments
use Getopt::Long 'GetOptions';
use File::Path qw( make_path );
use File::Copy qw( copy move);
use File::Find::Rule qw( );
GetOptions(
'prjroot=s' => \my $input_dir,
'outdir=s' => \my $output_dir,
);
my %created;
for my $in (
File::Find::Rule
->file()
->name(qr/^[^.].*\.yfg$/)
->in($input_dir)
) {
my $match_file = substr($in, length($input_dir) + 1);
my ($match_dir) = $match_file =~ m{^(.*)/} ? $1 : '.';
my $out_dir = $output_dir . '/' . $match_dir;
my $out = $output_dir . '/' . $match_file;
make_path($out_dir) if !$created{$out_dir}++;
copy($in, $out);
}
Error occured:
./generate.pl: line 1: use: command not found
./generate.pl: line 2: use: command not found
./generate.pl: line 3: syntax error near unexpected token `('
./generate.pl: line 3: `use CGI qw(:all);'
perl execution should be as follows:
I should copy the contents from one directory to another directory along with perl modulES(I.E File::Find::Rule)
./generate.pl -prjroot "/home/bharat/DATA" -outdir "/home/bharat/DATA1"
Help me fix my issues .
You miss the perl comment in the first line:
#!<path_to_perl>/perl
use strict;
use warnings 'all';
use CGI qw(:all);
#generate the user file arguments
.....
Your program will also work if you call it with the perl Interpreter in front of your command:
perl ./generate.pl -prjroot "/home/bharat/DATA" -outdir "/home/bharat/DATA1"
You've already seen what the problem is. But I'll just add that perldoc perldiag gives pretty good explanations for any error message you get from Perl. In this case, searching for "command not found" would give you this:
%s: Command not found
(A) You've accidentally run your script through csh or another shell instead of Perl. Check the #! line, or manually feed your script into Perl yourself. The #! line at the top of your file could look like
#!/usr/bin/perl -w
And that's particularly impressive, given that this error isn't actually generated by Perl - but by your shell.

Using commands inside scripts for Perl?

I trying to run a perl command inside a script and here is what I got:
filenumber1.txt:
94088076164765675
The command window looks okay:
C:\Users\Guest\Documents\Prime Numbers>perl -Mntheory=:all -nE "chomp; say next_prime($_);" filenumber1.txt
94088076164765687
I am trying to do this in a script as well called primenumbers.pl and generate another file called log.txt as the output file and filenumber1.txt as the input file:
#!/usr/bin/env perl
use warnings;
use strict;
use feature 'say';
use ntheory ":all";
# open filehandle log.txt
open (my $LOG, '>>', 'log.txt');
# select new filehandle
select $LOG;
perl -Mntheory=:all -nE "chomp; say next_prime($_);" filenumber1.txt
primenumbers.pl is in the same directory as filenumbers.txt and something is wrong when I run the script and I do not know what:
C:\Users\Guest\Documents\Prime Numbers>perl primenumbers.pl
Bareword found where operator expected at primenumbers.pl line 7, near ""say next_prime($_);" filenumber1.txt"
(Missing operator before filenumber1.txt?)
syntax error at primenumbers.pl line 7, near ""say next_prime($_);" filenumber1.txt"
Execution of primenumbers.pl aborted due to compilation errors.
I tried fixing it myself, but I only made matters worse, and there were more problems to fix. Does anyone know how to help me from here please on generating the output file "log.txt" without viewing the input file "filenumber1.txt"? Thanks in advance.
The -n switch to perl just wraps the code in while (<>) { ... }, so, to get a similar effect in your own program, just add the loop yourself (untested code; may contain errors):
#!/usr/bin/env perl
use warnings;
use strict;
use feature 'say';
use ntheory ":all";
# open filehandle log.txt
open (my $LOG, '>>', 'log.txt');
# select new filehandle
select $LOG;
while (<>) {
chomp; say next_prime($_);
}
Run this with
primenumbers.pl filenumber1.txt
and you should be set.

perl getopt::Long path to file

I'm trying to open an input file as an argument using the Getopt::Long module
This is the beginning of my script
#! /usr/bin/perl -s
use strict;
use warnings;
use Data::Dumper;
local $Data::Dumper::Useqq = 1;
use Getopt::Long qw(GetOptions);;
my $input='';
GetOptions('input|in=s' => \$input);
open(my $table1,'<', $input) or die "$! - [$input]"; #input file
And this is how I launch the script
$ script.pl -in /path/to/file.txt
I get as output:
No such file or directory - [] at script.pl line 13.
Line 13 is the line with open(....
Is there a mistake in the script?
You are using Perl's built-in option parsing with the -s in your shebang line. In a command like script.pl -in /path/to/file.txt that makes perl set the variable $in to 1 and remove the corresponding entry from #ARGV before Getopt::Long ever sees it
Just remove -s from the shebang line and everything it will work for you
No, there is no mistake in the script. Your code is doing what you told it to do.
It's calling the die "$! - [$input]"; part of that line, because the open returned a false value.
No such file or directory is the content of $!. That's the error it encountered. And between the [] there is the value of $input, which is empty. So there's your problem. You're passing an empty string to open, and that fails.
You are calling it the wrong way.
Getopt::Long requires options that are longer than one letter to be prefixed by --. This means that -in should be --in.
$ script.pl --in /path/to/file.txt
Because you didn't do that, Getopt::Long didn't see your option, and didn't parse it. A bit higher you initialized $input = '', so it stayed the empty string.
You could add a check to make sure that the input file is always provided.
use strict;
use warnings;
use Getopt::Long qw(GetOptions);;
my $input = '';
GetOptions('input|in=s' => \$input);
die 'the --input option is required!' unless $input;
open(my $table1,'<', $input) or die "$! - [$input]"; #input file

Awk not working inside a perl scipt?

I am trying to execute below awk command inside a perl script, but it is failing.
#!/usr/bin/perl
print `awk -F, '{print $NF}' f1.txt > f2.txt`
This is the error:
syntax error at ./MO.pl line 3, near "print"
Execution of ./MO.pl aborted due to compilation errors.
Can anyone please help what I am doing wrong here?
This is a Perl error and has nothing to do with your awk script itself. The error is usually seen when the previous statement doesn't have a semicolon at the end.
Here's a very simple program (which should include use strict; and use warnings;, but I wanted to emulate what you have).
#! /usr/bin/env perl
#
print "Hello, World\n" # Line 4
print "Hello, Back\n"; # Line 5
And the error message is:
syntax error at test.pl line 5, near "print"
Execution of test.pl aborted due to compilation errors.
Note the error is near the print in Line #5, but the error is actually at the end of Line #4 where I'm missing a semicolon.
Running your exact program works on my system (although doesn't quite produce the results you want). I am assuming this isn't your exact program, but instead a simplification of your program. Is there a statement before that print?
Several other things:
You're redirecting your awk output, so there's nothing to print.
Use strict and warnings.
Better to use qx(....) than backticks (grave accent). It's more readable and allows you to do quoted executable in quoted executable.
Watch for Perlisms in your code. The $NF is interpreted by Perl, and without the use strict;, doesn't give you an error. Instead, the print in your Awk statement is a null print which prints the entire line.
Why do you use print if nothing is printing out? You're better off in this position to use system which allows you to put single quotes around your entire statement:
system q(awk -F, '{print $NF}' f1.txt > f2.txt);
This way, $NF doesn't have to be quoted.
Why are you doing Awk in a Perl program? Perl will do anything Awk will do and do it better:
Here's a version of your program using plain ol' Perl:
#! /usr/bin/env perl
use strict;
use warnings;
use autodie;
while ( my $line = <> ) {
my #array = split /\s*,\s*/, $line;
print $array[-1];
}
To run this program:
$ test.pl f1.txt > f2.txt
Yes, it's longer, but half of the program is taken up by pragmas that all Perl programs should use.
I'm sure people smarter than me can turn this into a Perl one-liner.
Since you're redirecting the awk output, there's nothing for perl to print. You might as well use system and the quoting operator q():
system q(awk -F, '{print $NF}' f1.txt > f2.txt)
Or, of course, do it in perl, which saves you from having to spawn a shell and then spawn awk:
open my $in, '<', 'f1.txt';
open my $out, '>', 'f1.txt';
while (<$in>) {
print $out (split " ")[-1], "\n";
}
close $in;
close $out;
If there are more lines in the script, you need a semi-colon at the end of the print statement.

Perl 'system' failure messages

Say I have this perl "program" called simple.pl:
#!/usr/bin/perl
use xyz; # xyz is bogus and doesn't exist
And I also have this "program", called simple2.pl:
#!/usr/bin/perl
system("simple.pl");
my $abc = `simple.pl`;
printf("abc %s\n", $abc);
for both system and backtick, I get this message:
Can't exec "simple.pl": No such file or directory at scripts/perl/simple2.pl line 7.
Can't exec "simple.pl": No such file or directory at scripts/perl/simple2.pl line 9.
Not very useful for the user calling simple2.pl. Is there a way to get a more useful message?
Note. simple.pl does exist in the current directory. The real problem is that simple.pl doesn't compile. simple2 responds by saying simple doesn't exist. it's a misleading message.
If I had a way to even capture the compile message that would be a start.
This means system couldn't find an executable named "simple.pl" on your PATH. If your simple.pl is in the current directory, you could try to change "simple.pl" to "./simple.pl".
Actually, I don't see how to make this message more descriptive. If you were perl, how would you report this error?
BTW, I wouldn't try to run "simple2.pl" from inside of simple2.pl :)
Yes, check to see if the file exists and is executable, and if it isn't, print a more descriptive message.
unless (-ex $filename) {
print "I am unable to execute file $filename.";
}
If perl say it can't find the file, then it can't find the file. And the problem is more your code. Look at this example.
sidburn#sid:~/perl$ cat test.pl
#!/usr/bin/env perl
use strict;
use warnings;
use xyz;
sidburn#sid:~/perl$ cat test2.pl
#!/usr/bin/env perl
use strict;
use warnings;
system('test.pl');
sidburn#sid:~/perl$ cat test3.pl
#!/usr/bin/env perl
use strict;
use warnings;
system('./test.pl');
If you execute test2.pl you get:
sidburn#sid:~/perl$ ./test2.pl
Can't exec "test.pl": No such file or directory at ./test2.pl line 4.
If you execute test3.pl you get:
sidburn#sid:~/perl$ ./test3.pl
Can't locate xyz.pm in #INC (#INC contains: /home/sidburn/perl510/lib/5.10.1/i686-linux /home/sidburn/perl510/lib/5.10.1 /home/sidburn/perl510/lib/site_perl/5.10.1/i686-linux /home/sidburn/perl510/lib/site_perl/5.10.1 .) at ./test.pl line 4.
BEGIN failed--compilation aborted at ./test.pl line 4.
If you don't provide a relative or absolute path then perl lookup the command in your $PATH environment variable. If it is not there it can't find the file.
You need to provide "./" if it is in the current directory. But note "current directory" doesn't mean the directory where your script relies.
If you want the later then you probably want to do a
use FindBin;
with this you can do something like this:
#!/usr/bin/env perl
use strict;
use warnings;
use FindBin;
use File::Spec::Functions;
my $exe = catfile($FindBin::RealBin, 'test.pl');
print $exe, "\n";
system($exe);
if you want to check if system returns correctly, you need to check the return value from the system() command or $? later that holds the value.
if ( $? != 0 ) {
die "Cannot execute $exe.\n";
}
if you want to suppress messages from your program you need to redirect STDOUT, STDERR before starting your program with system().
Or use something like IPC::System::Simple
Or IPC::Open3 (in the core).
Bonus points for enabling the warnings pragma! Have an upvote!
You want to use backticks or qx// to capture the output of an external program, not system. To substitute your own error message that will make sense to your users (more points for you!), then you might do something as in
#! /usr/bin/perl
use strict;
use warnings;
no warnings 'exec';
chomp(my $abc = `simple2.pl`);
if ($? == 0) {
printf("abc %s\n", $abc);
}
else {
die "$0: unable to calculate abc\n";
}
In case you're unfamiliar, $? is
$CHILD_ERROR
$?
The status returned by the last pipe close, backtick command, successful call to wait or waitpid, or from the system operator.
When $? is zero, it indicates success.
Remember that the warnings pragma is lexical, so rather than disabling the warning for the whole program, you might do it for just one sub:
sub calculate_abc {
no warnings 'exec';
# ...
}
If you are trying to execute something you know is a Perl script, why not invoke the interpreter directly rather than dealing with the system knowing how to execute the file?
my $file = 'simple.pl';
-e $file or die "file '$file' not found";
system "perl $file";
# or
print `perl $file`;
to run with the same installation of perl that is running your current script:
system "$^X $file"; # or `$^X $file`
$^X is a special Perl variable that contains the file name of the running interpreter.
I had the exact same issue and figured out that perl wasn't installed. So the bash script was trying to execute the perl without an interpreter.
ls /usr/bin/perl
Try specifying the full path to the "simple.pl" file.