tags:

views:

91

answers:

5

Hi,

I have this file like this:

$cat a
hdisk1 active
hdisk2 active

I use this shell script to check:

$cat a.sh
#!/usr/bin/ksh
for d in 1 2
do
    grep -q "hdisk$d" a && echo "$d : ok"
done

Trying to convert this to Perl like this:

$cat b.sh
#!/usr/bin/ksh
export d
for d in 1 2
do
    cat a | perl -lane 'BEGIN{$d=$ENV{'d'};} print "$d: OK" if /hdisk$d\s+/'
done

I export the variable d in the shell script and get the value using %ENV in perl. Is there a better way of passing this value to the Perl one-liner?

Thanks.

A: 

Pass it on the command line, and it will be available in @ARGV:

for d in 1 2
do
  perl -lne 'BEGIN {$d=shift} print "$d: OK" if /hdisk$d\s+/' $d a
done

Note that the shift operator in this context removes the first element of @ARGV, which is $d in this case.

Greg Bacon
It is worth point out that @gbacon has converted `cat a| perl -n` to `perl -n a`. If you give a filename as a parameter to perl it is available to the -n loop.
justintime
A: 

That looks good, but I'd use:

for d in $(seq 1 2); do perl -nle 'print "hdisk$ENV{d} OK" if $_ =~ /hdisk$ENV{d}/' a; done
Eduardo
+1  A: 

You can enable rudimentary command line argument with the "s" switch. A variable gets defined for each argument starting with a dash. The -- tells where your command line arguments start.

for d in 1 2 ; do 
  cat a | perl -slane ' print "$d: OK" if /hdisk$d\s+/' -- -d=$d; 
done

See: http://perldoc.perl.org/perlrun.html

Philippe A.
+1  A: 

If you are having trouble writing a one liner, maybe it is a bit hard for one line (just my opinion). I would agree with @FM's suggestion and do the whole thing in Perl. Read the whole file in and then test it.

    use strict;
    local $/ = '' ; # read in whole file
    my $file = <> ;

    for my $d ( 1 .. 2 )
    {

       print  "$d: OK\n" if  $file =~ /hdisk$d\s+/
    }

You could do it looping but that would be longer. Of course it somewhat depends on the size of file.

Note that all the Perl examples so far will print a message for each match - can you be sure there are no duplicates?

justintime
A: 

Combining some of the earlier suggestions and adding my own sugar to it, I'd do it this way:

perl -se '/hdisk([$d])/ && print "$1: ok\n" for <>' -- -d='[value]' [file]

[value] can be a number (i.e. 2), a range (i.e. 2-4), a list of different numbers (i.e. 2|3|4) (or almost anything else, that's a valid pattern) or even a bash variable containing one of those, example:

d='2-3'
perl -se '/hdisk([$d])/ && print "$1: ok\n" for <>' -- -d=$d a 

and [file] is your filename (i.e. a).

dblu