我目前有以下正则表达式:
^\s*(.+)(?:[-\._ ]+)(\d+)\s*[xX]\s*(\d+)
这将匹配show_3x01_ep. name
并检索show
, 3
, 01
. 我想扩展它,以便可以捕获多个剧集。例如:
show _3x01_3x02 ep. name
应该返回:
show, 3, 01, 3, 02
有人可以向我解释如何做到这一点吗?
我目前有以下正则表达式:
^\s*(.+)(?:[-\._ ]+)(\d+)\s*[xX]\s*(\d+)
这将匹配show_3x01_ep. name
并检索show
, 3
, 01
. 我想扩展它,以便可以捕获多个剧集。例如:
show _3x01_3x02 ep. name
应该返回:
show, 3, 01, 3, 02
有人可以向我解释如何做到这一点吗?
您对正则表达式的期望过高。最简单的方法是分两步完成。
首先请注意,尽管您的示例中的(.+)
which 匹配项show
过于笼统。如果您将模式应用于show _3x01_3x02 ep. name
然后您将得到show
- 带有尾随空格 - 因为以下[-._ ]+
(无需转义点或将字符类括在 中(?: ... )
)仅满足一个字符。
这将按照您的要求进行。它查找第一个字母字符字符串,然后查找由单个x
.
use strict;
use warnings;
my $s = 'show _3x01_3x02 ep. name';
if ( my ($prefix) = $s =~ /([a-z]+)/i ) {
print "$prefix\n";
print "$1 $2\n" while $s =~ /(\d+)x(\d+)/g;
}
输出
show
3 01
3 02
您可以使用 Perl 的g正则表达式修饰符在字符串中多次扫描模式。然后,您可以将这些匹配项保存到列表中,然后对该列表或其各个元素执行某些操作。例如:
$ echo 'show _3x01_3x02 ep.name' |
perl -ne '@words = ($_ =~ /\A(.*?)(?=\d)|(\d+)x(\d+)/g);
@words = grep { $_ ne "" } @words;
while (my $idx = each @words) {
@words[$idx] =~ s/^\s+|\s+\b|_//g;
};
print join(", ", @words), "\n"'
show, 3, 01, 3, 02
您的文件名不一致,因此您最好扫描已知模式然后进行清理。我已经提供了 Perl 解决方案,但提供了这个 Ruby 解决方案作为替代方案。例如:
str = 'show _3x01_3x02 ep. name'
str.scan(/\A(.*?)(?=\d)|(\d+)x(\d+)/).
flatten.compact.map { |e| e.gsub(?_, ' ').strip }
#=> ["show", "3", "01", "3", "02"]
在这一行代码中发生了很多事情,但应该很容易理解。该代码将:
正则表达式本身与 Perl 兼容,但其余逻辑依赖于 Ruby 的String#scan和其他可能无法直接映射到 Perl 的内部结构。YMMV。