Perl的grep函数如何与正则表达式配合使用?

4
以下是grep函数的工作原理(!/0o1Iil]/的作用是什么?):
@chars = grep !/0o1Iil]/, 0..9, "A".."Z", "a".."z"; 
use Data::Dumper; 
print Dumper @chars;

以 @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个回答

6
这里是grep perldoc。你例子中的语句使用了grep EXPR,LIST语法,意味着任何Perl表达式都可以替代EXPR
grep接收提供给它的列表,并返回只有在EXPR为真时的项。
在这种情况下,EXPR是! /0o1Iil]/(为了可读性添加了空格),意思是“该项没有被正则表达式/0o1Iil]/匹配”。由于这些项都不被那个正则表达式匹配(它们都不包含字符串0o1Iil]),所以它们都被返回。
正如其他帖子中提到的那样,正则表达式可能本来应该写成/[0o1Iil]/,这将删除可能会混淆的字符,例如0和o,1和I。这对于密码或序列号等很有用。
顺便说一下,你可以将grep重写为更明确的BLOCK形式,并使LIST构造明确化。
@chars = grep { ! /[0o1Iil]/ } (0..9, 'A'..'Z', 'a'..'z');

这个例子看起来好像本应该有一个开括号,这样grep就可以匹配除了0、o、1、I、i和l之外的所有内容。 - Cascabel
是的,听起来这似乎是为生成密码或序列号等设计的,其中不应该出现歧义字符。 - rjh
是的,我错过了开头的方括号。谢谢你的答案。 - Lydon Ch
是的,这个程序旨在生成密码。 - Lydon Ch

2

// 是一个正则表达式匹配运算符。!/[0o1Iil]/ 表示“不匹配方括号中的任何字符”。我认为你在第一个斜杠后面缺少了一个左方括号([) - 目的是过滤掉所有可能被误认为是其他字符的字符(0/O,I/l/1)。


1
Perl grep 的一般语法是:

grep BLOCK LIST

它对LIST中每个元素计算BLOCK,并返回由那些表达式计算为true的元素组成的列表值。

在您的情况下,BLOCK!/0o1Iil]/,该代码段为那些不包含模式0o1Iil]的元素返回true。由于在您的情况下,没有一个LIST元素包含该模式,grep会返回整个LIST

如果BLOCK像这样:!/[0o1Iil]/,该代码段将为那些不包含零、小写字母“o”、“1”、“I”、“i”或“l”的元素返回true,则您将得到除这些元素以外的所有元素作为结果的LIST


0

grep函数作为列表的过滤器。

在这种情况下,列表是所有字母数字字符。

过滤器由正则表达式指定。 表示not。换句话说,结果列表应该排除与正则表达式匹配的任何项。

正则表达式试图匹配任何出现的0o1Iil](不是0o1Iil,因为在集合开头省略[将防止正则表达式将]视为字符类元字符。

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

看到列表0..9,A..Z,a..z不包含0o1Iil]的任何出现,因此没有要过滤的项目,这就是为什么您会得到整个字母数字字符列表的原因。

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

列表中任何与0o1Iil匹配的项目都将被过滤掉。因此,您将获得不包含上述六个字符的字母数字列表。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接