views:

1491

answers:

6

As I understand (Perl is new to me) Perl can be used to script against a Unix command line. What I want to do is run (hardcoded) command line calls, and search the output of these calls for RegEx matches. Is there a way to do this simply in Perl? How?

EDIT: Sequence here is: -Call another program. -Run a regex against its output.

+2  A: 
#!/usr/bin/perl

sub my_action() {
        print "Implement some action here\n";
}

open PROG, "/path/to/your/command|" or die $!;
while (<PROG>) {
        /your_regexp_here/ and my_action();
        print $_;
}
close PROG;

This will scan output from your command, match regexps and do some action (which now is printing the line)

Quassnoi
maybe it would be better to replace the print statement with a do block .
Geo
This doesn't run any of the desired "(hardcoded) command line calls", it just reads and acts on standard input.
ephemient
+2  A: 

Do you need Perl at all? How about

command -I use | grep "myregexp" && dosomething

right in the shell?

Arkadiy
This is going to be happening hundreds of times, and I'm going to be adding an output file, so yes. But your command is pretty similar to the one Perl will be shooting out :P
bigwoody
for output file, "tie". But for hundreds of times... May be Perl.
Arkadiy
+2  A: 

In Perl you can use backticks to execute commands on the shell. Here's a document on this. I'm not sure about how to capture the output, but I'm sure there's more than a way to do it.

tunnuz
+7  A: 
my $command = "ls -l /";
my @output = `$command`;
for (@output) {
    print if /^d/;
}

The qx// quasi-quoting operator (for which backticks are a shortcut) is stolen from shell syntax: run the string as a command in a new shell, and return its output (as a string or a list, depending on context). See perlop for details.

You can also open a pipe:

open my $pipe, "$command |";
while (<$pipe>) {
    # do stuff
}
close $pipe;

This allows you to (a) avoid gathering the entire command's output into memory at once, and (b) gives you finer control over running the command. For example, you can avoid having the command be parsed by the shell:

open my $pipe, '-|', @command, '< single argument not mangled by shell >';

See perlipc for more details on that.

ephemient
Or as I ended up implementing it:for (@output) { my_action() if /regex/;}Allowing me to do whatever I want if I get a hit. Thanks!
bigwoody
+2  A: 

You might be able to get away without Perl, as others have mentioned. However, if there is some Perl feature you need, such as extended regex features or additional text manipulation, you can pipe your output to perl then do what you need. Perl's -e switch let's you specify the Perl program on the command line:

command | perl -ne 'print if /.../'

There are several other switches you can pass to perl to make it very powerful on the command line. These are documented in perlrun. Also check out some of the articles in Randal Schwartz's Unix Review column, especially his first article for them. You can also google for Perl one liners to find lots of examples.

brian d foy
Haven't you omitted the -n flag here?
reinierpost
A: 

You indeed use a one-liner in a case like this.

I recently coded up a little modulino that I use, among other ways, to produce output which lists the directory structure present in a .zip archive (one dir entry per line). So using that output as an example of command output that we'd like to filter, we could put a pipe in and then use perl with the -n -e flags to filter the incoming data (and/or do other things with it):

[command_producing_text_output] | perl -MFile::Path -n -e \
   "BEGIN{@PTM=()} if (m{^perl/(bin|lib(?!/site))}) {chomp;push @PTM,$_}" ^
-e "END{@WDD=mkpath (\@PTM,1);" ^
-e "printf qq/Created %u dirs to reflect part of structure present in the .ZIP file\n/, scalar(@WDD);}"

the shell syntax used, including: quoting of perl code and escaping of newlines, reflects CMD.exe usage in Windows NT-like consoles. If you need to, mentally replace "^" with "\" and " with ' in the appropriate places.

The one-liner above adds only the directory names that start with "perl/bin" or "perl/lib (not followed by "/site"); it then creates those directories. You wind up with a (empty) tree that you can use for whatever evil purposes you desire.

The main point is to illustrate that there are flags available (-n, -p) to allow perl to loop over each input record (line), and that what you can do is unlimited in terms of complexity.