【发布时间】:2017-06-22 02:11:54
【问题描述】:
我有一个配置 .ini 文件,用户可以在其中使用 Perl 正则表达式或 Ant 通配模式指定文件模式。例如,以下内容将禁止用户创建 Windows 下不允许的文件:
[BAN Defined using Ant Globbing]
file = **/prn.*
ignorecase = true
[BAN Defined using Regular expressions]
match = /(aux|con|com[0-9]*|lpt[0-9]*|nul|clock$)\.?[a-z]$
ignorecase = true
现在,我必须将 glob 转换为正则表达式才能以编程方式处理它。我有一个例行程序,但它有点复杂。我正在寻找以下之一:
- 将 glob 转换为正则表达式的简单方法
- 使用正则表达式匹配全局表达式的方法。
例如:
if ($regex =~ /\/(aux|con|com[0-9]*|lpt[0-9]*|nul|clock$)\.?[a-z]$) {
if ($glob ?magic? /**/prn.*/) {
我希望有一些神奇的 Perl 方法可以做到这一点。那么,有没有一种简单的不能错过的方法:
顺便说一句,如果有人感兴趣,这是我的子程序:
sub glob2regex {
my $glob = shift;
my $regex = undef;
my $previousAstrisk = undef;
foreach my $letter (split(//, $glob)) {
#
# ####Check if previous letter was astrisk
#
if ($previousAstrisk) {
if ($letter eq "*") { #Double astrisk
$regex .= ".*";
$previousAstrisk = undef;
next;
} else { #Single astrisk: Write prev match
$regex .= "[^/]*";
$previousAstrisk = undef;
}
}
#
# ####Quote all Regex characters w/ no meaning in glob
#
if ($letter =~ /[\{\}\.\+\(\)\[\]]/) {
$regex .= "\\$letter";
#
# ####Translate "?" to Regular expression equivelent
#
} elsif ($letter eq "?") {
$regex .= ".";
#
# ####Don't know how to handle astrisks until the next line
#
} elsif ($letter eq "*") {
$previousAstrisk = 1;
#
# ####Convert backslashes to forward slashes
#
} elsif ($letter eq '\\') {
$regex .= "/";
#
# ####Just a letter
#
} else {
$regex .= $letter;
}
}
#
# ####Handle if last letter was astrisk
#
if ($previousAstrisk) {
$regex .= "[^/]*";
}
#
# ####Globs are anchored to both beginning and ending
#
$regex = "^$regex\$";
return $regex;
}
【问题讨论】:
-
有search.cpan.org/perldoc?Text::Glob 和search.cpan.org/perldoc?File::Glob。前者为正则表达式提供类 glob 匹配,后者为文件系统实现类 glob 匹配。
-
我希望有一些 Perl 大师知道的巧妙技巧(比如能够通过
@{[function]}语法在引用的字符串中插入函数),而普通人和我们二流的编程黑客都不知道.我看到了Text::Glob,但它并没有扩展 Ant 风格的扩展 glob。 -
您能否指出 Ant 样式 glob 扩展的可靠定义?也许一个参考点会帮助想出一个解决方案。