tags:

views:

247

answers:

5

Hi,

How does the following grep function works (what does !/0o1Iil]/ do? )

@chars = grep !/0o1Iil]/, 0..9, "A".."Z", "a".."z"; 
use Data::Dumper; 
print Dumper @chars;

to produce the following in @chars?

$VAR1 = 0;
$VAR2 = 1;
$VAR3 = 2;
$VAR4 = 3;
$VAR5 = 4;
$VAR6 = 5;
$VAR7 = 6;
$VAR8 = 7;
$VAR9 = 8;
$VAR10 = 9;
$VAR11 = 'A';
$VAR12 = 'B';
$VAR13 = 'C';
$VAR14 = 'D';
$VAR15 = 'E';
$VAR16 = 'F';
$VAR17 = 'G';
$VAR18 = 'H';
$VAR19 = 'I';
$VAR20 = 'J';
$VAR21 = 'K';
$VAR22 = 'L';
$VAR23 = 'M';
$VAR24 = 'N';
$VAR25 = 'O';
$VAR26 = 'P';
$VAR27 = 'Q';
$VAR28 = 'R';
$VAR29 = 'S';
$VAR30 = 'T';
$VAR31 = 'U';
$VAR32 = 'V';
$VAR33 = 'W';
$VAR34 = 'X';
$VAR35 = 'Y';
$VAR36 = 'Z';
$VAR37 = 'a';
$VAR38 = 'b';
$VAR39 = 'c';
$VAR40 = 'd';
$VAR41 = 'e';
$VAR42 = 'f';
$VAR43 = 'g';
$VAR44 = 'h';
$VAR45 = 'i';
$VAR46 = 'j';
$VAR47 = 'k';
$VAR48 = 'l';
$VAR49 = 'm';
$VAR50 = 'n';
$VAR51 = 'o';
$VAR52 = 'p';
$VAR53 = 'q';
$VAR54 = 'r';
$VAR55 = 's';
$VAR56 = 't';
$VAR57 = 'u';
$VAR58 = 'v';
$VAR59 = 'w';
 $VAR60 = 'x';
 $VAR61 = 'y';
 $VAR62 = 'z';
+4  A: 

Here's the grep perldoc. The statement in your example is using the grep EXPR,LIST syntax, which means any Perl expression can take the place of EXPR.

grep takes the list provided to it, and returns only the items where EXPR is true.

EXPR in this case is ! /0o1Iil]/ (space added for readability) which means "this item is not matched by the regex /0o1Iil]/. Since none of those items are matched by that regular expression (none of them contain the string 0o1Iil]) they are all returned.

As other posters have mentioned, the regex was probably supposed to read /[0o1Iil]/, which would remove characters that could be confused, e.g. 0 and o, 1 and I. This sounds useful for passwords or serial numbers, etc.

Btw, you could rewrite the grep into the clearer BLOCK form, and make the LIST construction explicit:

@chars = grep { ! /[0o1Iil]/ } (0..9, 'A'..'Z', 'a'..'z');
rjh
This example really looks like there was supposed to be an open bracket, so that the grep would match everything except the 0, o, 1, I, i, and l.
Jefromi
Yes, sounds like this was designed to generate passwords or serial numbers etc. where ambiguous characters should not be present.
rjh
yes I missed the opening square bracket. thanks for the answer.
portoalet
and yes this was designed to generate passwords.
portoalet
A: 

It doesn't have any effect here. (Probably there should be square brackets around the pattern).

As the manpage states, the grep function

Evaluates the BLOCK or EXPR for each element of LIST (locally setting $_ to each element) and returns the list value consisting of those elements for which the expression evaluated to true.

In your example the expression is !/0o1Iil]/ which is negated pattern match.

eugene y
+2  A: 

// is a regular expression match operator. !/[0o1Iil]/ means “does not match any of the characters in the square brackets.” And I think you’re missing an opening square bracket ([) after the first slash – the intention is to filter out all characters that could be mistaken for some other (0/O, I/l/1).

zoul
+1 for spotting the missing `[`
vladr
+1  A: 

The general syntax of a Perl grep is:

grep BLOCK LIST

It evaluates the BLOCK for each element of LIST and returns the list value consisting of those elements for which the expression evaluated to true.

In your case BLOCK is !/0o1Iil]/ which return true for those elements which do not contain the pattern 0o1Iil]. Since in your case none of the LIST elements contain that pattern, the grep returns entire LIST.

Had the BLOCK been like: !/[0o1Iil]/ which returns true for those elements which do not contain a zero, or a lowercase o, or a 1, or a I, or a i or a l, then you would have got a LIST with all but these elements as the result.

codaddict
A: 

The grep function acts as a filter on lists.

In this case, the list is all alphanumeric characters.

The filter is specified by a regular expression. The ! denotes not. In other words, the resulting list should exclude whatever items match the regular expression.

The regular expression is trying to match any occurrence of 0o1Iil] (not 0o1Iil, because omitting a [ at the beginning of the set will prevent the regular expression from seeing the ] as the character class metacharacter.

grep {not /0o1Iil]/} 0..9, A..Z, a..z (Without the [):

Seeing that the list 0..9, A..Z, a..z contains no occurrence of 0o1Iil], there are no items to filter out, which is why you get your entire list of alphanumeric characters back.

grep {not /[0o1Iil]/} 0..9, A..Z, a..z (With the [):

Any items in the list matching 0, o, 1, I, i or l will be filtered out. Thus, you'll get your alphanumeric list back, sans the above-mentioned six characters.

Zaid