我希望能够从命令行中获取一个参数,并将其用作我脚本中的正则表达式来过滤我文件中的行。一个简单的例子
$ perl script.pl id_4
在script.pl中:
...
my $exp = shift;
while(my $line = <$fh){
if($line =~ /$exp/){
print $line,"\n";
}
}
...
我的实际脚本有点复杂,并且对该行进行其他操作以提取信息并生成不同的输出。我的问题是我想要过滤掉包含“id_4”的每一行,而不是仅包含“id_4”的选择行。通常这可以通过
来实现if($line !~ /$exp/)
但是,如果可能的话,我不想改变我的脚本以接受更复杂的参数集(例如,如果第二个参数是“ne”,则使用!~
,如果不是,则使用=~
任何人都可以想到我可以使用的正则表达式(除了长“id_1 | id_2 | id_3 | id_5 ...”之外)从多种可能性中过滤掉包含一个特定值的行吗?我担心我在这里要求愚蠢,应该坚持理智并接受进一步的论证:/。
答案 0 :(得分:1)
为什么选择?有两个。
my $exp = join "|", grep !/^!/, @ARGV;
my @not = grep /^!/, @ARGV;
s/^!// for @not;
my $exp_not = join "|", @not;
...
if (( $line =~ $exp ) && ( $line !~ $exp_not )) {
# do stuff
}
<强>用法:强>
perl script.pl orange soda !light !diet
答案 1 :(得分:0)
有一种方法可以反转正则表达式,因此您可以执行匹配,例如“所有不包含subexpr
匹配的字符串”。如果没有直接表达这一点的运算符(即仅使用基本的正匹配正则表达式运算符),它仍然可能会导致大而笨重的正则表达式(可能是正则表达式大小中的组合爆炸)。
举一个简单的例子,看看我对这个问题的回答:如何编写一个匹配除字符串“help”之外的所有内容的正则表达式。 (这是一个相当简化的比赛,以匹配开始和结束。)Match all letter/number combos but specific word?
当您想要将表达式的匹配反转为整体时,传统的Unix工具会出现问题:grep
与grep -v
。或者vi
::g/pat/
与:v/pat/
等等。通过这种方式,实现者避免了实现不适合简单NFA构造方法的困难正则表达式运算符。
最简单的事情就是做同样的事情并且有一个粗粒度否定的约定:包含模式和排除模式。