I have a command in perl
system("grep LISTEN /root/Desktop/m.txt | awk {'print $5'} | cut -f 1 -d ":"| sort | uniq > /tmp/entropy/dsip.txt");
The output error near $5.
How to write $5 the same string, not a valuable ?
Calling awk and cut and sort from Perl? Really? Perl can do all the work itself:
open my $LISTEN, '<', '/root/Desktop/m.txt' or die $!;
my %uniq;
while (<$LISTEN>) {
next unless /LISTEN/;
my $fifth = (split)[4];
$fifth =~ s/:.*//;
undef $uniq{$fifth};
}
print $_, "\n" for sort keys %uniq;
Use non interpolating parentheses,
system(q{grep LISTEN ..});
Just escape the $s:
print "\$literal\n";
to prevent Perl from interfering. Also escape the $s, to prevent shell from interfering:
system("echo \\\$1");
in which case shell will see \$1 and echo will see $1.
awk {'print $5'}
should be
awk '{print $5}'
ikegami says: The above is wrong since the two are equivalent
$ perl -E'say "<$_>" for #ARGV' awk {'print $5'}
<awk>
<{print $5}>
$ perl -E'say "<$_>" for #ARGV' awk '{print $5}'
<awk>
<{print $5}>
Related
I have a list of PCs and I need to append quotes and commas to each of them so that I can do a SQL query
List example
Row1|PCName|PC1.local
Row2|PCName|PC2.local
Row3|PCName|PC3.local
and I need to get this
"PC1.local", "PC2.local", "PC3.local", ......
Here is what I tried
cat list.txt | awk -F\| '{print $NF}' | perl -e 'while(<>){ print "\"$_\", ";}'
I get this
", "PC1.local
", "PC2.local
", "PC3.local
", "
How can I make those PCs show up in a single line and with the format that I need?
I know using awk or perl might be overkill for this and it could be done using Perl alone or awk alone, but I'm interested in learning how to pipe things to Perl. How can I make Perl print those PC names in the format I need?
How about:
#!/usr/bin/env perl
use strict;
use warnings;
print join ",", map { chomp; '"'.(split /\|/)[2].'"' } <DATA> ;
__DATA__
Row1|PCName|PC1.local
Row2|PCName|PC2.local
Row3|PCName|PC3.local
Output:
"PC1.local","PC2.local","PC3.local"
As a one liner:
perl -e 'print join ",", map { s/\n//; q{"}.(split /\|/)[2].q{"} } <>'
$ awk -F'|' '{printf "%s\"%s\"", (NR>1?", ":""), $3} END{print ""}' file
"PC1.local", "PC2.local", "PC3.local"
with unix toolset
$ cut -d'|' -f3 file | sed 's/.*/"&"/' | paste -s -d,
extract third field, wrap with quotes, join with comma
Here's a Perl one-line solution
$ perl -le 'print join ", ", map { /([^|\s]+)$/ && qq{"$1"} } <>' myfile
output
"PC1.local", "PC2.local", "PC3.local"
#!perl
use strict;
use warnings;
while ( my $line = readline(*STDIN) ) {
chomp $line;
my #machines = split /\|/, $line;
print join(',', map { '"' . $_ . '"' } #machines), "\n";
}
Output:
$ cat list.txt | perl test.pl
"Row1","PCName","PC1.local"
"Row2","PCName","PC2.local"
"Row3","PCName","PC3.local"
How to add a blank line after every grep result?
For example, grep -o "xyz" may give something like -
file1:xyz
file2:xyz
file2:xyz2
file3:xyz
I want the output to be like this -
file1:xyz
file2:xyz
file2:xyz2
file3:xyz
I would like to do something like
grep "xyz" | perl (code to add a new line after every grep result)
This is the direct answer to your question:
grep 'xyz' | perl -pe 's/$/\n/'
But this is better:
perl -ne 'print "$_\n" if /xyz/'
EDIT
Ok, after your edit, you want (almost) this:
grep 'xyz' * | perl -pe 'print "\n" if /^([^:]+):/ && ! $seen{$1}++'
If you don’t like the blank line at the beginning, make it:
grep 'xyz' * | perl -pe 'print "\n" if /^([^:]+):/ && ! $seen{$1}++ && $. > 1'
NOTE: This won’t work right on filenames with colons in them. :)½
If you want to use perl, you could do something like
grep "xyz" | perl -p -e 's/(.*)/\1\n/g'
If you want to use sed (where I seem to have gotten better results), you could do something like
grep "xyz" | sed 's/.*/\0\n/g'
This prints a newline after every single line of grep output:
grep "xyz" | perl -pe 'print "\n"'
This prints a newline in between results from different files. (Answering the question as I read it.)
grep 'xyx' * | perl -pe '/(.*?):/; if ($f ne $1) {print "\n"; $f=$1}'
Use a state machine to determine when to print a blank line:
#!/usr/bin/env perl
use strict;
use warnings;
# state variable to determine when to print a blank line
my $prev_file = '';
# change DATA to the appropriate input file handle
while( my $line = <DATA> ){
# did the state change?
if( my ( $file ) = $line =~ m{ \A ([^:]*) \: .*? xyz }msx ){
# blank lines between states
print "\n" if $file ne $prev_file && length $prev_file;
# set the new state
$prev_file = $file;
}
# print every line
print $line;
}
__DATA__
file1:xyz
file2:xyz
file2:xyz2
file3:xyz
This is what I'm trying to do:
$variable = `grep -i "Text: Added to directory" '$FOO/result.txt' | awk '{print $6}' | tr -d "'"`
print $variable;
Output:
Text: Added to directory /path/to/directory/
Use of uninitialized value $6 in concatenation (.) or string
How can I fetch just "/path/to/directory" instead of "Text: Added to directory /path/to/directory/"?
Of course Perl can do what grep, awk and tr can do.
open my $fh, "<", "$FOO/result.txt" or die "can't open file: $!\n";
while (<$fh>) {
next unless /pattern/i;
(my $six = (split)[5]) =~ tr/'//d;
print $six, "\n";
}
close $fh;
You probably need to adjust the quote-escaping but this should do:
awk IGNORECASE=1 '/yourpattern/{ gsub(/\'/, \'\'); print $6 }' $FOO/result.txt
AWK is pretty versatile.
I have a list:
asd#domain.com
fff#domain.com
yyy#domain.com
ttt#test.com
rrr#test.com
fff#test.com
yyy#my.com
yyy#my.com
How it possible to do this:
if in whole list we see three or more email with same domain - all duplicates except first one need to remove.
Output:
asd#domain.com
ttt#test.com
yyy#my.com
yyy#my.com
#!/usr/bin/env perl
use strict; use warnings;
use Email::Address;
my %data;
while (my $line = <DATA>) {
my ($addr) = Email::Address->parse($line =~ /^(\S+)/);
push #{ $data{ $addr->host } }, $addr->original;
}
for my $addrs (values %data) {
if (#$addrs > 2) {
print "$addrs->[0]\n";
}
else {
print "$_\n" for #$addrs;
}
}
__DATA__
asd#domain.com
fff#domain.com
yyy#domain.com
ttt#test.com
rrr#test.com
fff#test.com
yyy#my.com
yyy#my.com
sed -s 's/#/#\t/g' test.txt | uniq -f 1 | sed -s 's/#\t/#/g'
The first sed separates the email in 2 fields (name + domain) with a tab character, so that uniq can skip the first field when removing the duplicate domains, and the last sed removes the tab.
I am puzzled why your example output contains yyy#my.com twice but assume it is a mistake.
As long as there are no issues with trailing space characters or more complex forms of email addresses you can do this simply in Perl with
perl -aF# -ne 'print unless $seen{$F[1]}++' myfile
output
asd#domain.com
ttt#test.com
yyy#my.com
This might work for you:
sed ':a;$!N;s/^\([^#]*#\([^\n]*\)\)\n.*\2/\1/;ta;P;D' file
asd#domain.com
ttt#test.com
yyy#my.com
If you don't mind the order, just use sort:
sort -t '#' -u -k 2,2 your_file
If you do mind the order, do
gawk '{print NR "#" $0}' your_file | sort -t '#' -u -k 3,3 | sort -t '#' -k 1,1n | cut -d \# -f 2-
How could I convert:
awk '{print $2 >> $1}' file
in a short Perl one-liner?
"file" could look like this:
fruit banana
vegetable beetroot
vegetable carrot
mushroom chanterelle
fruit apple
there may some other ways, but here's what i can think of
perl -ane 'open(FILE,">>",$F[0]); print FILE $F[1];close(FILE);' file
I guess awk has to be better at some things :-)
This is right at the limit of what I'd do on the command line, but it avoids reopening filehandles.
$ perl -lane '$fh{$F[0]} || open $fh{$F[0]}, ">>", $F[0]; print {$fh{$F[0]}} $F[1]' file
Not pure Perl, but you can do:
perl -nae '`echo $F[1] >> $F[0]`' input_file
This is what a2p <<< '{print $2 >> $1}' produces
#!/usr/bin/perl
eval 'exec /usr/bin/perl -S $0 ${1+"$#"}'
if $running_under_some_shell;
# this emulates #! processing on NIH machines.
# (remove #! line above if indigestible)
eval '$'.$1.'$2;' while $ARGV[0] =~ /^([A-Za-z_0-9]+=)(.*)/ && shift;
# process any FOO=bar switches
$, = ' '; # set output field separator
$\ = "\n"; # set output record separator
while (<>) {
($Fld1,$Fld2) = split(' ', $_, -1);
&Pick('>>', $Fld1) &&
(print $fh $Fld2);
}
sub Pick {
local($mode,$name,$pipe) = #_;
$fh = $name;
open($name,$mode.$name.$pipe) unless $opened{$name}++;
}