... | perl -pe "s/([^$filespec]*)($filespec)/ ...
$filespec
所以我有一个函数,如果大多数情况下,上述结构都可以正常工作。然而如果文件名中有破折号我收到一条Invalid [] range
消息。
如何确保变量$filespec
扩展为不受此类解析错误影响的文件名?
答案1
关键假设 -$filespec
只是您想要匹配的一组字符。这是不是一个正则表达式。
让我们用一些代码来模拟这个问题
filespec = 'z-a'
perl -e 'print "MATCH\n" if "DEF" =~ /$filespec/'
use strict;
use warnings;
my $filespec = 'z-a';
print "Match\n" if "DEF" =~ m/[^$filespec]/ ;
跑步可以给
Invalid [] range "z-a" in regex; marked by <-- HERE in m/[^z-a <-- HERE ]/ at try line 6.
$filespec
当正则表达式中的 扩展为 时,会触发该问题m/[^z-a]/
。在这种情况下z-a
是无效的字符范围。
要解决此问题,您需要(至少)转义-
in $filespec
。使用quotemeta
应该可以解决问题,就像这样
use strict;
use warnings;
my $filespec = quotemeta 'z-a';
print "Match\n" if "DEF" =~ m/[^$filespec]/ ;
输出是
Match
将其包含到管道命令的模拟中。首先是失败的命令版本
filespec='z-a'
perl -e "print qq[MATCH\n] if 'DEF' =~ /[^$filespec]/"
跑步给
Invalid [] range "z-a" in regex; marked by <-- HERE in m/[^z-a <-- HERE ]/ at -e line 1.
这是固定版本
filespec='z-a';
filespec=`perl -e "print quotemeta qq[$filespec]"`
perl -e "print qq[MATCH\n] if 'DEF' =~ /[^$filespec]/"
答案2
括号表达式中的破折号被视为范围,除非它用反斜杠1转义或者是表达式中的第一个或最后一个字符(或者,如果用^
后面的第一个字符^
或最后一个字符对表达式进行否定)。
例如
[a-z]
匹配从a
到 的所有小写字符z
(但请参阅注释 2)
[a\-z]
、[-az]
和[az-]
全部仅匹配 3 个字符:-
、a
和z
。
并且,正如 @pmqs 在他们的答案中指出的那样,[z-a]
这是一个无效范围,并且会生成错误。
如果您的正则表达式包含带有一个或多个破折号的括号表达式,那么您需要对其进行修改,以便它按您的预期工作。与大多数事情一样,您需要充分了解您正在使用的软件和语言功能,以使它们执行您想要/期望的操作。
请参阅man perlre
参考资料 来了解有关 perl 正则表达式的详细信息,包括便利功能和您需要注意的其他“陷阱”。该手册页中有很多内容,您不可能一下子掌握所有内容。当您需要时再回顾一下,您将在未来几年内更多地了解它的工作原理。另请参阅man perlrequick
快速参考和man perlretut
教程。有关man perlrecharclass
perl 中的字符类和括号表达式的更多信息。有关man perlrebackslash
Perl 中反斜杠和转义序列的更多信息。
(如果您的 linux 发行版或 unix 没有可用作man
页面的 perl 文档,则使用perldoc
作为运行命令,而不是man
,例如perldoc perlre
)。
鉴于 Perl 有五个主要手册页,总计约 54000 字的散文和示例,专门用于正则表达式(还有两个您可能永远不需要的:perlreguts
描述 perl 正则表达式引擎如何工作和perlreapi
描述 perlre 的插件接口),您可能会开始猜测这是一个复杂的话题 - 你是对的。
笔记:
1并非所有正则表达式引擎都支持括号表达式内的转义字符。 Perl 可以,但大多数不可以 - 例如 GNU grep 的 BRE(默认,或-G
)和 ERE ( -E
) 不可以,但 GNU grep 的 perl 兼容 ( -P
) 正则表达式可以。
2 [[:alpha:]]
,[[:upper:]]
或者[[:lower:]]
通常更适合匹配字母字符,因为它们可以处理 unicode 文本以及纯 ASCII。[[:alnum:]]
与字母数字字符一样。