Beefy Boxes and Bandwidth Generously Provided by pair Networks
"be consistent"
 
PerlMonks  

How to awk a grep result in-script

by ShipWreck (Initiate)
on Nov 14, 2019 at 17:31 UTC ( [id://11108686]=perlquestion: print w/replies, xml ) Need Help??

ShipWreck has asked for the wisdom of the Perl Monks concerning the following question:

Good morning Monks, I'm trying to do the bash equivalent of awk on a grep output of a linux process. The idea is to extract the process ID of an application running on the server. Code looks like this:

#!/usr/bin/perl @array = `ps -ef | grep kdfadm`; @A = grep (/\/opt\/kdf\/home/, @array); my @A = split; print $A[1];

Code output (shortened for readability):

[kdfadm@srv01 ~]$ /usr/bin/perl SplitTest kdfadm 121562 121527 0 Nov13 ? 00:01:15 /opt/kdf/home/jdk1.8 +.0_162/jre/bin/java -Xms512m -Xmx512m ... [kdfadm@srv01 ~]$

I've come to grasp that the output is essentially the first line, as opposed to the first field. How do I perform the equivalent of "awk {'print $1,$2,$8'}" in perl?

Replies are listed 'Best First'.
Re: How to awk a grep result in-script
by haukex (Archbishop) on Nov 14, 2019 at 18:29 UTC

    A bare split operates on the special variable $_, but you're not setting that in your script.

    If you want to do this in a oneliner, see perlrun for the -n and -a switches. For example, if I understand your requirement, the command line ps -ef | perl -lane 'print $F[1] if /kdfadm/ && m{/opt/kdf/home}' should do what you want.

    However, the preferred method is to write a script, and to use modules appropriate for the task. For example, you might want to look at Proc::ProcessTable. There is no need to call the external tools awk, sed, or grep, as that can be written entirely in Perl. In the (rare) cases you do need to run an external command, I wrote about that here, with example code. Update: Maybe if you can tell us more about what the bigger picture is, we can help with more specific suggestions.

Re: How to awk a grep result in-script
by hippo (Bishop) on Nov 14, 2019 at 18:51 UTC
    How do I perform the equivalent of "awk {'print $1,$2,$8'}" in perl?

    Here is the answer to this particular question, although see haukex's reply (++) for some better approaches regarding the wider topic of shelling out.

    #!/usr/bin/env perl use strict; use warnings; my $in = 'z y x w v u t s r q p'; my @chars = split (/ /, $in); print "@chars[0,1,7]\n";

    Note that arrays in Perl by default start indexing from zero. Don't change this default unless you enjoy being hunted down by your co-developers.

Re: How to awk a grep result in-script
by karlgoethebier (Abbot) on Nov 14, 2019 at 18:49 UTC

    Some more ideas. Regards, Karl

    «The Crux of the Biscuit is the Apostrophe»

    perl -MCrypt::CBC -E 'say Crypt::CBC->new(-key=>'kgb',-cipher=>"Blowfish")->decrypt_hex($ENV{KARL});'Help

Re: How to awk a grep result in-script
by marioroy (Prior) on Nov 16, 2019 at 03:29 UTC

    Hi, ShipWreck

    Here are Perl snippets resembling awk and grep. The open statement emits a warning to the terminal if the command doesn't exist. Thus the reason simply exiting with status 127 matching the status in shell.

    Shell

    $ ps -ef | awk '{ print $1,$2,$8 }' | grep '^kdfadm ' $ ps -ef | awk '{ if ($1 == "kdfadm") print $1,$2,$8 }'

    Perl (no delays, fast like awk)

    use strict; use warnings; $, = ' '; # set output field separator $\ = "\n"; # set output record separator open my $cmd, 'ps -ef |' or exit(127); while (<$cmd>) { my ($f1,$f2,undef,undef,undef,undef,undef,$f8) = split(' ',$_,-1); print $f1,$f2,$f8 if ($f1 eq 'kdfadm'); } close $cmd;

    Perl using Proc::ProcessTable (suggestion by haukex and 1nickt)

    use strict; use warnings; use Proc::ProcessTable; $, = ' '; # set output field separator $\ = "\n"; # set output record separator my $t = Proc::ProcessTable->new(); my $uid = getpwnam('kdfadm'); foreach my $p (@{ $t->table }) { print @{ $p }{qw( uid pid cmndline )} if ($p->uid == $uid); }

    Regards, Mario

Re: How to awk a grep result in-script
by 1nickt (Canon) on Nov 15, 2019 at 14:30 UTC

    Hi, welcome to Perl, the One True Religion.

    " How do I perform the equivalent of "awk {'print $1,$2,$8'}" in perl?"

    We have tools.

    use strict; use warnings; use feature 'say'; use Proc::ProcessTable; my $t = Proc::ProcessTable->new; foreach my $p (@{$t->table}) { next unless $p->cmndline =~ m{/Applications/iTerm.app/Contents/Mac +OS/iTerm2}; say sprintf('%s : %s : %s', @{ $p }{qw/uid pid cmndline/}); }
    $ perl 11108686.pl 501 : 608 : /Applications/iTerm.app/Contents/MacOS/iTerm2 501 : 610 : /Applications/iTerm.app/Contents/MacOS/iTerm2 --server log +in -fp 1nickt 501 : 7264 : /Applications/iTerm.app/Contents/MacOS/iTerm2 --server lo +gin -fp 1nickt

    Hope this helps!


    The way forward always starts with a minimal test.
Re: How to awk a grep result in-script
by ShipWreck (Initiate) on Nov 14, 2019 at 19:39 UTC

    Found it:

    foreach my $line (@array) { my @column = split( /\s+/, $line ); print $column[0], " ", $column[1], " ", $column[7],"\n"; my $columnID = $column[0]; foreach ( my $columnID ) { while ( $columnID =~ /(^FBgn\d+)/ ) { my $ID = $1; print $ID, "\n"; } } }

    Which yields:

    [kdfadm@serv01 ~]$ /usr/bin/perl SplitTest root 10053 sudo kdfadm 10057 -bash root 24073 sudo kdfadm 24077 -bash kdfadm 28868 scp kdfadm 28869 /usr/bin/ssh kdfadm 29005 /usr/bin/perl kdfadm 29006 sh kdfadm 29007 ps kdfadm 29008 grep root 111587 sudo kdfadm 111592 -bash kdfadm 121521 /bin/sh kdfadm 121527 /opt/kdf/home/java8/bin/java kdfadm 121562 /opt/kdf/home/jdk1.8.0_162/jre/bin/java kdfadm 121563 /opt/kdf/home/jdk1.8.0_162/jre/bin/java kdfadm 121572 /opt/kdf/home/jdk1.8.0_162/jre/bin/java kdfadm 121576 /opt/kdf/home/jdk1.8.0_162/jre/bin/java kdfadm 121597 /opt/kdf/home/jdk1.8.0_162/jre/bin/java kdfadm 121600 /opt/kdf/home/jdk1.8.0_162/jre/bin/java kdfadm 121615 /opt/kdf/home/jdk1.8.0_162/jre/bin/java kdfadm 121622 /opt/kdf/home/jdk1.8.0_162/jre/bin/java

    Thanks to anyone who had a look.

      Found it: ...
      ... my $columnID = $column[0]; foreach ( my $columnID ) { while ( $columnID =~ /(^FBgn\d+)/ ) { my $ID = $1; print $ID, "\n"; } } ...
      I'm not sure if you mean that you've found a solution or a problem (or perhaps it refers to some out-of-band discussion, e.g., the Chatterbox), but the quoted loop code is puzzling:
      • my $columnID = $column[0]; defines and assigns a value to a lexical that is never accessed in the remainder of its scope;
      • foreach ( my $columnID ) { ... } defines a masking lexical that is assigned no value and so is undefined by default;
      • while ( $columnID =~ /(^FBgn\d+)/ ) { ... } matches the undefined masking lexical (odd that this produced no warning message... you do have warnings enabled, don't you?) against a pattern that cannot possibly match it (if there were a match, the loop would run forever).
      c:\@Work\Perl\monks>perl -le "use strict; use warnings; ;; my $columnID = 'XXX'; foreach ( my $columnID ) { while ( $columnID =~ /(^X)/ ) { my $ID = $1; print qq{$ID \n}; } } " Use of uninitialized value in pattern match (m//) at -e line 1.


      Give a man a fish:  <%-{-{-{-<

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://11108686]
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others studying the Monastery: (5)
As of 2024-04-24 23:20 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found