awk usage in perl scripting - perl

Hi am writing a script which its need to grep the 6th column of the output using awk command but am getting other output.
What is the exact syntax in perl to extract 6th column using awk?
#!/usr/bin/perl
use strict;
use warnings;
use diagnostics;
my $filesystem=`df -h |grep -i dev|grep -vE '^Filesystem|proc|none|udev|tmpfs'`;
print "(\"$filesystem\"|awk '{print \$6}')"
Output :
7831c1c4be8c% ./test.pl
("/dev/disk1 112Gi 43Gi 69Gi 39% 11227595 18084674 38% /
devfs 183Ki 183Ki 0Bi 100% 634 0 100% /dev
"|awk '{print $6}')%
Am trying to remove the % how it can be done ?
7831c1c4be8c% cat test.pl
#!/usr/bin/perl
use warnings;
use strict;
open my $FS, q(df -h |) or die $!;
while (<$FS>) {
print +(split)[4], "\n"
if /dev/i and not /devfs/;
}
7831c1c4be8c% ./test.pl
40%

You don't need awk inside Perl.
#!/usr/bin/perl
use warnings;
use strict;
open my $FS, '-|', q(df -h) or die $!;
while (<$FS>) {
print +(split)[5], "\n"
if /dev/i and not /^Filesystem|proc|none|udev|tmpfs/;
}

as the previous answer says, you don't need awk or grep system calls in perl. however, I will tell you that one reason your code isn't working is because you never made the awk system call. print does not execute the system call. you would have to use system() to execute it.
anyway fwiw you can also do what you want in a one-liner like so:
df -h | perl -lnae 'next if $F[0] =~ /regex/; print $F[5]'

Related

How to replace characters in a file utf8 in perl?

I have something like this (it works):
perl -C -MText::Unidecode -n -i -e'print unidecode( $_)' unicode_text.txt
and now i want to do the same in the script:
#!/usr/bin/perl -w -CSA
use utf8;
use Text::Unidecode;
while(<>)
{
print unidecode($_);
}
but it doesn't work.
You should have got the error message
Too late for "-CSA" option
which is what makes the program read the input file as UTF-8-encoded.
Instead you need to put
use open qw( :std :utf8 );
before the while loop, which does the same as -CS on the command line, i.e. to set the STDIN, STDOUT and STDERR handles to UTF-8 encoding

Running a background process in perl

I have a process which when
executed as below:
process_name > file.txt
will redirect all the output to file.txt and also to the console.
when executed like this
process_name >& file.txt&
will redirect the output to file.txt but will not print the output to console returning the pid on the console.
Now i want to execute the second way of running the process inside a perl script!
how could i do this?
currently i am usng the below method:
#!/usr/bin/perl
use strict;
use warnings;
my $res = `bsm_adjust_controller -F -ra -d 'subnetwork=NETSim_STD/bsc=0005' -f /tmp/31102012/Task_31102012_1421_0005.log >& /tmp/31102012/Ctrl_31102012_1421_0005.log&`;
print $res;
when i run the script it gives:
./temp.pl
sh: /tmp/31102012/Ctrl_31102012_1421_0005.log: bad number
I also tried the below method:
#!/usr/bin/perl
use strict;
use warnings;
my $res = "bsm_adjust_controller -F -ra -d 'subnetwork=NETSim_STD/bsc=0005' -f /tmp/31102012/Task_31102012_1421_0005.log >& /tmp/31102012/Ctrl_31102012_1421_0005.log&";
open(CMD, '-|', $res) || die "couldn't run $res: $!\n";
Even the above script throws the same error.
the purpose is to execute the process in background and continue with the next statements without caring what happened to the process and also i donot need the output of the process being run inside to console.
could anybody please help?
well this worked:
#!/usr/bin/perl
use strict;
use warnings;
my $cmd="bsm_adjust_controller -F -ra -d 'subnetwork=NETSim_STD/bsc=0106' -f /tmp/31102012/Task_31102012_1421_0005.log >/tmp/31102012/Ctrl_31102012_1421_0005.log";
open STDERR, ">/dev/null";
print "Redirected stderr to /dev/null\n";
my $pid=open (FH, "-|",$cmd);
if ($pid) { #parent
print "/tmp/31102012/Task_31102012_1421_0005.log";
exit;
}
print "Redirected stderr to /dev/null\n";
close(FH);

How to delete first line of file in perl script

How can i remove first line of txt file in perl script?
`sed "1d" filename.txt`
Dosen't work.
You can use Tie::File:
use Tie::File;
tie #array, 'Tie::File', $filename or die $!;
shift #array;
untie #array;
`sed 1d filename.txt > newfile.txt`
should work. If you don't redirect it to a file, it will just read the whole file minus the first line to stdout.
That sends to the output to sed's STDOUT (which Perl proceeds to capture into a variable) instead of filename.txt. You want to use sed's -i.
sed -i "1d" filename.txt
Since there's no output to capture, it makes no sense to use backticks. You want system.
system('sed -i "1d" filename.txt');
Better: (Avoids launching another shell)
system('sed', '-i', '1d', 'filename.txt');
Best: (Does error checking for you)
use IPC::System::Simple qw( systemx );
systemx('sed', '-i', '1d', 'filename.txt');
Because you're doing this using an inline sed, here is a Perl equiv..
perl -ne'$.==1?next:print' <(seq 1 10)
Where the options mean,
-n assume "while (<>) { ... }" loop around program
-e program one line of program (several -e's allowed, omit programfile)
Other notes,
$. is the variable for the current line number.
<() is Bash voodoo for generating a FIFO in the background.

Perl - One liner file edit: "perl -n -i.bak -e "print unless /^$id$,/" $filetoopena;" Not working

I cannot get this to work.
#!/usr/bin/perl -w
use strict;
use CGI::Carp qw(fatalsToBrowser warningsToBrowser);
my $id='123456';
my $filetoopen = '/home/user/public/somefile.txt';
file contains:
123456
234564
364899
437373
So...
A bunch of other subs and code
if(-s $filetoopen){
perl -n -i.bak -e "print unless /^$id$,/" $filetoopen;
}
I need to remove the line that matches $id from file $filetoopen
But, I don't want script to "crash" if $id is not in $filetoopen either.
This is in a .pl scripts sub, not being run from command line.
I think I am close but, after reading for hours here, I had to resort to posting the question.
Will this even work in a script?
I tried TIE with success but, I need to know alternatively how to do this without TIE::FILE.
When I tried I got the error:
syntax error at mylearningcurve.pl line 456, near "bak -e "
Thanks for teaching this old dog...
First of all (this is not the cause of your problem) $, (aka $OUTPUT_FIELD_SEPARATOR) defaults to undef, I'm not sure why you are using it in the regex. I have a feeling the comma was a typo.
It's unclear if you are calling this from a shell script or from Perl?
If from Perl, you should not call a nested Perl interpreter at all.
If the file is small, slurp it in and print:
use File::Slurp;
my #lines = read_file($filename);
write_file($filename, grep { ! /^$id$/ } #lines);
If the file is large, read line by line as a filter.
use File::Copy;
move($filename, "$filename.old") or die "Can not rename: $!\n";
open(my $fh_old, "<", "$filename.old") or die "Can not open $filename.old: $!\n";
open(my $fh, ">", $filename) or die "Can not open $filename: $!\n";
while my $line (<$fh_old>) {
next if $line =~ /^id$/;
print $fh $_;
}
close($fh_old);
close($fh);
If from a shell script, this worked for me:
$ cat x1
123456
234564
364899
437373
$ perl -n -i.bak -e "print unless /^$id$/" x1
$ cat x1
234564
364899
437373
if(-s $filetoopen){
perl -n -i.bak -e "print unless /^$id$,/" $filetoopen;
}
I'm not at all sure what you expect this to do. You can't just put a command line program in the middle of Perl code. You need to use system to call an external program. And Perl is just an external program like any other.
if(-s $filetoopen){
system('perl', '-n -i.bak -e "print unless /^$id$,/"', $filetoopen);
}
The functionality of the -i command line argument can be accessed via $^I.
local #ARGV = $filetoopen;
local $^I = '.bak';
local $_;
while (<>) {
print if !/^$id$/;
}

Perl: Redirect STDOUT to two files

How can I redirect the STDOUT stream to two files (duplicates) within my Perl script? Currently I am just streaming into a single log file:
open(STDOUT, ">$out_file") or die "Can't open $out_file: $!\n";
What do I have to change? Thx.
You can also use IO::Tee.
use strict;
use warnings;
use IO::Tee;
open(my $fh1,">","tee1") or die $!;
open(my $fh2,">","tee2") or die $!;
my $tee=IO::Tee->new($fh1,$fh2);
select $tee; #This makes $tee the default handle.
print "Hey!\n"; #Because of the select, you don't have to do print $tee "Hey!\n"
And yes, the output works:
> cat tee1
Hey!
> cat tee2
Hey!
Use the tee PerlIO layer.
use PerlIO::Util;
*STDOUT->push_layer(tee => "/tmp/bar");
print "data\n";
$ perl tee_script.pl > /tmp/foo
$ cat /tmp/foo
data
$ cat /tmp/bar
data
File::Tee provides the functionality you need.
use File::Tee qw( tee );
tee(STDOUT, '>', 'stdout.txt');
If you're using a Unix-like system, use the tee utility.
$ perl -le 'print "Hello, world"' | tee /tmp/foo /tmp/bar
Hello, world
$ cat /tmp/foo /tmp/bar
Hello, world
Hello, world
To set up this duplication from within your program, set up a pipe from your STDOUT to an external tee process. Passing "|-" to open makes this easy to do.
#! /usr/bin/env perl
use strict;
use warnings;
my #copies = qw( /tmp/foo /tmp/bar );
open STDOUT, "|-", "tee", #copies or die "$0: tee failed: $!";
print "Hello, world!\n";
close STDOUT or warn "$0: close: $!";
Demo:
$ ./stdout-copies-demo
Hello, world!
$ cat /tmp/foo /tmp/bar
Hello, world!
Hello, world!