How do I echo string with bash command more in Perl? - perl

This is what I tried:
my $s = "s" x 1000;
my $r = `echo $s |more`;
But it doesn't work, my program exits directly...

It does not work in your example, because you never print $r. The output is captured in the variable $r. By using system() instead, you can see the output printed to STDOUT, but then you cannot use the output as you (probably) expected.
Just do:
print $r;
Update: I changed say to print, since "echo" already gives you a newline.
To escape shell meta characters, as mentioned in the comments, you can use quotemeta.
You should also be aware that | more has no effect when capturing output from the shell into a variable. The process is simply: echo | more | $r, and you might as well skip more.

try with the system() command :
my $s = "s" x 1000;
my $r = system("echo $s |more");
will display all your 's', and in $r you will have the result (0 in this case) of the command.

Related

Perl hangs up on while loop

This code hangs up for some reason or just doesn't go any further when while (<>) { $file .= $_}; is queried. Why is that?
As soon as I start the code with the entered text does not happen more than that it outputs task1 and then it hangs.
Code:
#!/usr/bin/perl -w
use strict;
use JSON;
my $json = JSON->new->allow_nonref;
my $file = "";
print('task1');
while (<>) { $file .= $_ };
print('task2');
my $json_output = $json->decode( $file );
my ($c, $i, $cstr, $istr);
foreach my $cert (#$json_output) {
print('task3');
$i = $json_output->{i};
$c = $json_output->{c};
$istr = join("", map { sprintf("%02x",$_) } #$i);
$cstr = pack("C*", #$c);
open(F, ">$istr.der"); print F $cstr; close(F);
print('done.');
}
Output:
task1
This line
while (<>) { $file .= $_ };
is trying to read from a file specified on the command line, or if there isn't one, from standard input. If there isn't anything piped to standard input, then it sits waiting for you to type something at the keyboard.
So I'm guessing you didn't specify a file on the command line, and your program is sitting there waiting to get input from standard input.
Also, the easier way to read in the entire file to a single variable is like so:
my $file = do { local $/; <> };
See this article for other options.
How do you invoke your code? The <> operator means that it takes input from either all the files that you specify as arguments, or from standard input. If you call your script with no arguments, it will sit and wait for console input.
If you call it without arguments, try entering a few lines of text when it is "hanging", and then type Ctrl+D if you are on Linux, or Ctrl+Z on Windows. That should make the script work.

Why is there a 0 on a new line when I print in perl?

I'm trying to get the inode alone of a file that is passed through as an argument.
When I extract the inode, however, there is a 0 printed on a new line. I've tried to get rid of it with regex but I can't. I'm passing the script /usr/bin/vim The 0 isn't there when I run the command (ls -i /usr/bin/vim | awk '{print $1}'), but it is when I run my script.
How can I get rid of this 0?
my $filepath = $ARGV[0];
chomp $filepath;
$filepath =~ s/\s//g;
print ("FILEPATH: $filepath\n"); #looks good
my $inode = system("ls -i $filepath | awk '{print \$1}'");
$inode =~ s/[^a-zA-Z0-9]//g;
$inode =~ s/\s//g;
print ("$inode\n");
So my result is
137699967
0
When you invoke system you run the command provided as its argument, and that's what's outputting the inode number.
The return value of system is the exit code of the command run, which in this case is 0, and that's what your subsequent print call outputs.
To run an external program and capture its output, use the qx operator, like so:
my $inode = qx/ls -i $filepath | awk '{print \$1}'"/;
However, as Sobrique explained in their answer, you don't actually need to call an external program, you can use Perl's built-in stat function instead.
my $inode = stat($filepath)[1];
stat returns a list containing a variety of information about a file - index 1 holds its inode. This code won't handle if the file doesn't exist, of course.
Don't, just use the stat builtin instead
print (stat($filepath))[1]."\n";
print join "\n", map { (stat)[1] } #ARGV,"\n"

how to run a shell command in perl in backticks when command also has backticks

example.
$output= `eval `environment` ; echo $Variable` ;
i want to execute this command
eval `environment` ; echo $Variable
in a perl script.
$output= `eval `environment` ; echo $Variable` ;
Use the qx// form from the "Quote-like Operators":
my $output = qx{eval `environment` ; echo $Variable};
But that still probably wouldn't do what you want, since $Variable would be already evaluated and interpolated by Perl. To fix that:
# single quotes:
my $command = q{eval `environment` ; echo $Variable};
# and then execute it:
my $output = qx{$command};
Alternatively, a little hack:
my $output = qx'eval `environment` ; echo $Variable';
When the ' is used as the character to the quote-like operators, it inhibits the variable interpolation.
You may use Backtiks "here documents" - see Backtics sub section in man perlop for details. $ sign must be escaped if you want to avoid variable expansion by perl.
#!/usr/bin/perl
use strict;
use warnings;
my $output = <<`END`;
eval `environment` ; echo \$Variable
END
print $output;

Why does this Perl code work from the shell, but not from a script?

I have a simple question. I have been using the zoidberg perl shell to get myself familiarized with perl interactively. I like being able to test my stuff on the fly before I flesh out a script. (I am a novice learner.)
My question is, in the shell I can do the following:
#a = `df -h | grep /dev/mapper | cut -c 48-`
for $i (#a) { #b=`ls $i` }
print #b;
However, when I put this in a script in linux:
#!/bin/perl
I see the following error when I run the script:
syntax error at perl_diskstats.perl line 5, near "$i ( "
Execution of perl_diskstats.perl aborted due to compilation errors.
Am I doing something obvious here? What exactly am I doing wrong? I thought the format was..
foreach $var (#array) { codeblock }
... right?
You're missing a semi-colon at the end of your first line.
Also you are missing use strict, and the my declarations.
use strict;
my #a = `df -h | grep /dev/mapper | cut -c 48-`;
my #b;
for my $i (#a) { #b=`ls $i` }
print #b;
Start off on the habit of use strict now, while you're still beginning. It will save you in the longterm.

get output of execution perl

Usually to get the output of a command I run from perl I use back tick
my $value = `pwd`;
How do I do it though if I need to insert a variable within the back ticks ``?
Text inside backticks is interpolated before it is passed to the operating system in the same way as text inside double quotes. So these statements all do what they look like they do:
$value = `$command`;
$value = `$someCommand $arg`;
$value = `$someOtherCommand #list`;
qx() is another way of running an external command and returning the output. If for some reason you don't want Perl to interpolate your command, you can run qx with the single-quote delimiter.
$value = qx'echo $PATH'; # shell's $PATH, not Perl's $PATH
You can just insert it. E.g.
my $dir = "/home"
my $text = `ls -l $dir`;
print $text;
my $hello = "world";
my $value = ` echo $hello `;
print $value;
Use qx() instead of backticks. Eg. my ($used, $dir); ($used) = qx(du -k $dir);